1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-04-20 05:49:26 +03:00

v4.19-9582-beta

This commit is contained in:
dnobori
2015-10-06 20:18:00 +09:00
parent 3c8abd60ed
commit 4e862a7e40
59 changed files with 4281 additions and 109 deletions
+10
View File
@@ -556,6 +556,16 @@ BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, boo
return b;
}
// Raw IP bridge is supported only on Linux
bool IsRawIpBridgeSupported()
{
#ifdef UNIX_LINUX
return true;
#else // UNIX_LINUX
return false;
#endif // UNIX_LINUX
}
// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
// Department of Computer Science has dozens of overly-enthusiastic geeks.
+4
View File
@@ -126,6 +126,9 @@
#endif // OS_WIN32
// Constants
#define BRIDGE_SPECIAL_IPRAW_NAME "ipv4_rawsocket_virtual_router"
// Bridge
struct BRIDGE
{
@@ -171,6 +174,7 @@ bool DeleteLocalBridge(CEDAR *c, char *hubname, char *devicename);
bool IsBridgeSupported();
bool IsNeedWinPcap();
UINT GetEthDeviceHash();
bool IsRawIpBridgeSupported();
#endif // BRIDGE_H
+791 -3
View File
@@ -374,7 +374,7 @@ TOKEN_LIST *GetEthListSolaris()
#ifdef UNIX_LINUX
// Get Ethernet device list on Linux
TOKEN_LIST *GetEthListLinux()
TOKEN_LIST *GetEthListLinux(bool enum_normal, bool enum_rawip)
{
struct ifreq ifr;
TOKEN_LIST *t;
@@ -383,6 +383,11 @@ TOKEN_LIST *GetEthListLinux()
LIST *o;
char name[MAX_SIZE];
if (enum_normal == false && enum_rawip)
{
return ParseToken(BRIDGE_SPECIAL_IPRAW_NAME, NULL);
}
o = NewListFast(CompareStr);
s = UnixEthOpenRawSocket();
@@ -431,7 +436,7 @@ TOKEN_LIST *GetEthListLinux()
Sort(o);
t = ZeroMalloc(sizeof(TOKEN_LIST));
t->NumTokens = LIST_NUM(o);
t->NumTokens = LIST_NUM(o) + (enum_rawip ? 1 : 0);
t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
for (i = 0;i < LIST_NUM(o);i++)
@@ -440,6 +445,11 @@ TOKEN_LIST *GetEthListLinux()
t->Token[i] = name;
}
if (enum_rawip)
{
t->Token[t->NumTokens - 1] = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
}
ReleaseList(o);
return t;
@@ -542,11 +552,15 @@ TOKEN_LIST *GetEthListBpf()
// Enumerate Ethernet devices
TOKEN_LIST *GetEthList()
{
return GetEthListEx(NULL, true, false);
}
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip)
{
TOKEN_LIST *t = NULL;
#if defined(UNIX_LINUX)
t = GetEthListLinux();
t = GetEthListLinux(enum_normal, enum_rawip);
#elif defined(UNIX_SOLARIS)
t = GetEthListSolaris();
#elif defined(BRIDGE_PCAP)
@@ -575,6 +589,11 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
return NULL;
}
if (StrCmpi(name, BRIDGE_SPECIAL_IPRAW_NAME) == 0)
{
return OpenEthLinuxIpRaw();
}
if (tapmode)
{
#ifndef NO_VLAN
@@ -732,6 +751,10 @@ UINT EthGetMtu(ETH *e)
{
return 0;
}
if (e->IsRawIpMode)
{
return 0;
}
if (e->CurrentMtu != 0)
{
@@ -802,6 +825,10 @@ bool EthSetMtu(ETH *e, UINT mtu)
{
return false;
}
if (e->IsRawIpMode)
{
return false;
}
if (mtu == 0)
{
@@ -865,6 +892,11 @@ bool EthIsChangeMtuSupported(ETH *e)
return false;
}
if (e->IsRawIpMode)
{
return false;
}
return true;
#else // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
return false;
@@ -1526,6 +1558,13 @@ void CloseEth(ETH *e)
return;
}
if (e->IsRawIpMode)
{
CloseEthLinuxIpRaw(e);
return;
}
if (e->Tap != NULL)
{
#ifndef NO_VLAN
@@ -1647,6 +1686,11 @@ UINT EthGetPacketLinux(ETH *e, void **data)
return INFINITE;
}
if (e->IsRawIpMode)
{
return EthGetPacketLinuxIpRaw(e, data);
}
if (e->Tap != NULL)
{
#ifndef NO_VLAN
@@ -1949,6 +1993,11 @@ void EthPutPacket(ETH *e, void *data, UINT size)
{
return;
}
if (e->IsRawIpMode)
{
EthPutPacketLinuxIpRaw(e, data, size);
return;
}
if (size < 14 || size > MAX_PACKET_SIZE)
{
Free(data);
@@ -2017,6 +2066,745 @@ void EthPutPacket(ETH *e, void *data, UINT size)
Free(data);
}
// Open ETH by using IP raw packets
ETH *OpenEthLinuxIpRaw()
{
ETH *e;
if (IsRawIpBridgeSupported() == false)
{
return NULL;
}
e = ZeroMalloc(sizeof(ETH));
e->IsRawIpMode = true;
e->RawTcp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_TCP), NULL);
e->RawUdp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_UDP), NULL);
e->RawIcmp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_ICMP), NULL);
if (e->RawTcp == NULL || e->RawUdp == NULL || e->RawIcmp == NULL)
{
ReleaseSock(e->RawTcp);
ReleaseSock(e->RawUdp);
ReleaseSock(e->RawIcmp);
Free(e);
return NULL;
}
ClearSockDfBit(e->RawTcp);
ClearSockDfBit(e->RawUdp);
ClearSockDfBit(e->RawIcmp);
SetRawSockHeaderIncludeOption(e->RawTcp, true);
SetRawSockHeaderIncludeOption(e->RawUdp, true);
SetRawSockHeaderIncludeOption(e->RawIcmp, true);
e->Name = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
e->Title = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
e->Cancel = NewCancel();
UnixDeletePipe(e->Cancel->pipe_read, e->Cancel->pipe_write);
e->Cancel->pipe_read = e->Cancel->pipe_write = -1;
UnixSetSocketNonBlockingMode(e->RawTcp->socket, true);
UnixSetSocketNonBlockingMode(e->RawUdp->socket, true);
UnixSetSocketNonBlockingMode(e->RawIcmp->socket, true);
e->Cancel->SpecialFlag = true;
e->Cancel->pipe_read = e->RawTcp->socket;
e->Cancel->pipe_special_read2 = e->RawUdp->socket;
e->Cancel->pipe_special_read3 = e->RawIcmp->socket;
e->RawIpMyMacAddr[2] = 0x01;
e->RawIpMyMacAddr[5] = 0x01;
SetIP(&e->MyIP, 10, 171, 7, 253);
SetIP(&e->YourIP, 10, 171, 7, 254);
e->RawIpSendQueue = NewQueueFast();
e->RawIP_TmpBufferSize = 67000;
e->RawIP_TmpBuffer = Malloc(e->RawIP_TmpBufferSize);
return e;
}
// Close ETH by using IP raw packets
void CloseEthLinuxIpRaw(ETH *e)
{
if (e == NULL)
{
return;
}
while (true)
{
BUF *buf = GetNext(e->RawIpSendQueue);
if (buf == NULL)
{
break;
}
FreeBuf(buf);
}
ReleaseQueue(e->RawIpSendQueue);
Free(e->Name);
Free(e->Title);
ReleaseSock(e->RawTcp);
ReleaseSock(e->RawUdp);
ReleaseSock(e->RawIcmp);
ReleaseCancel(e->Cancel);
Free(e->RawIP_TmpBuffer);
Free(e);
}
// Receive an IP raw packet
UINT EthGetPacketLinuxIpRaw(ETH *e, void **data)
{
UINT r;
BUF *b;
// Validate arguments
if (e == NULL || data == NULL)
{
return INFINITE;
}
if (e->RawIp_HasError)
{
return INFINITE;
}
b = GetNext(e->RawIpSendQueue);
if (b != NULL)
{
UINT size;
*data = b->Buf;
size = b->Size;
Free(b);
return size;
}
r = EthGetPacketLinuxIpRawForSock(e, data, e->RawTcp, IP_PROTO_TCP);
if (r == 0)
{
r = EthGetPacketLinuxIpRawForSock(e, data, e->RawUdp, IP_PROTO_UDP);
if (r == 0)
{
r = EthGetPacketLinuxIpRawForSock(e, data, e->RawIcmp, IP_PROTO_ICMPV4);
}
}
if (r == INFINITE)
{
e->RawIp_HasError = true;
}
return r;
}
// Receive an IP raw packet for the specified socket
UINT EthGetPacketLinuxIpRawForSock(ETH *e, void **data, SOCK *s, UINT proto)
{
UCHAR *tmp;
UINT r;
IP src_addr;
UINT src_port;
UINT ret = INFINITE;
UCHAR *retbuf;
PKT *p;
bool ok = false;
// Validate arguments
if (e == NULL || data == NULL)
{
return INFINITE;
}
tmp = e->RawIP_TmpBuffer;
LABEL_RETRY:
*data = NULL;
r = RecvFrom(s, &src_addr, &src_port, tmp, e->RawIP_TmpBufferSize);
if (r == SOCK_LATER)
{
return 0;
}
if (r == 0)
{
if (s->IgnoreRecvErr)
{
return 0;
}
else
{
return INFINITE;
}
}
ret = 14 + r;
retbuf = Malloc(ret);
*data = retbuf;
Copy(retbuf, e->RawIpYourMacAddr, 6);
Copy(retbuf + 6, e->RawIpMyMacAddr, 6);
retbuf[12] = 0x08;
retbuf[13] = 0x00;
Copy(retbuf + 14, tmp, r);
// Mangle packet
p = ParsePacket(retbuf, ret);
if (p != NULL)
{
if (p->TypeL3 == L3_IPV4)
{
IPV4_HEADER *ip;
IP original_dest_ip;
ip = p->L3.IPv4Header;
UINTToIP(&original_dest_ip, ip->DstIP);
if (IsZeroIP(&e->MyPhysicalIPForce) == false && CmpIpAddr(&e->MyPhysicalIPForce, &original_dest_ip) == 0 ||
(IsIPMyHost(&original_dest_ip) && IsLocalHostIP(&original_dest_ip) == false && IsHostIPAddress4(&original_dest_ip)))
{
if (IsZeroIP(&e->MyPhysicalIPForce) && CmpIpAddr(&e->MyPhysicalIP, &original_dest_ip) != 0)
{
// Update MyPhysicalIP
Copy(&e->MyPhysicalIP, &original_dest_ip, sizeof(IP));
// Debug("e->MyPhysicalIP = %r\n", &e->MyPhysicalIP);
}
if (IsZeroIP(&e->MyPhysicalIPForce) == false)
{
Copy(&e->MyPhysicalIP, &e->MyPhysicalIPForce, sizeof(IP));
}
ip->DstIP = IPToUINT(&e->YourIP);
ip->Checksum = 0;
ip->Checksum = IpChecksum(ip, IPV4_GET_HEADER_LEN(ip) * 5);
if (p->TypeL4 == L4_TCP)
{
TCP_HEADER *tcp = p->L4.TCPHeader;
/*
if (Endian16(tcp->SrcPort) == 80)
{
IP a, b;
UINTToIP(&a, ip->SrcIP);
UINTToIP(&b, ip->DstIP);
Debug("%r %r %u %u\n", &a, &b, Endian16(tcp->SrcPort), Endian16(tcp->DstPort));
}*/
ok = true;
}
else if (p->TypeL4 == L4_UDP)
{
UDP_HEADER *udp = p->L4.UDPHeader;
udp->Checksum = 0;
ok = true;
}
else if (p->TypeL4 == L4_ICMPV4)
{
ICMP_HEADER *icmp = p->L4.ICMPHeader;
if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
{
// Rewrite the Src IP of the IPv4 header of the ICMP response packet
UINT size = p->PacketSize - ((UCHAR *)icmp - (UCHAR *)p->PacketData);
UCHAR *data = (UCHAR *)icmp;
IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
UINT orig_ipv4_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
if (orig_ipv4_header_size >= sizeof(IPV4_HEADER) && orig_ipv4_size >= orig_ipv4_header_size)
{
if (orig_ipv4->Protocol == IP_PROTO_ICMPV4)
{
// Search the inner ICMP header
UINT inner_icmp_size = orig_ipv4_size - orig_ipv4_header_size;
if (inner_icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
{
ICMP_HEADER *inner_icmp = (ICMP_HEADER *)(((UCHAR *)data) +
sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
if (inner_icmp->Type == ICMP_TYPE_ECHO_REQUEST)
{
ICMP_ECHO *inner_echo = (ICMP_ECHO *)(((UCHAR *)inner_icmp) + sizeof(ICMP_HEADER));
inner_icmp->Checksum = 0;
orig_ipv4->SrcIP = IPToUINT(&e->YourIP);
orig_ipv4->Checksum = 0;
orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
// Rewrite the outer ICMP header
if (true)
{
UCHAR *payload;
UINT payload_size;
ICMP_ECHO *echo;
// Echo Response
echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
{
payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
// Rewrite the header
icmp->Checksum = 0;
icmp->Checksum = IpChecksum(icmp, size);
}
}
}
}
}
}
}
icmp->Checksum = 0;
icmp->Checksum = IpChecksum(icmp, p->PayloadSize);
ok = true;
}
else if (p->TypeL4 == L4_FRAGMENT)
{
ok = true;
}
}
}
FreePacket(p);
}
if (ok == false)
{
Free(*data);
*data = NULL;
goto LABEL_RETRY;
}
return ret;
}
// Send internal IP packet (insert into the send queue)
void EthSendIpPacketInnerIpRaw(ETH *e, void *data, UINT size, USHORT protocol)
{
BUF *b;
if (e == NULL || data == NULL || size == 0)
{
return;
}
if (e->RawIpSendQueue->num_item >= 1024)
{
return;
}
b = NewBuf();
WriteBuf(b, e->RawIpYourMacAddr, 6);
WriteBuf(b, e->RawIpMyMacAddr, 6);
WriteBufShort(b, protocol);
WriteBuf(b, data, size);
SeekBufToBegin(b);
InsertQueue(e->RawIpSendQueue, b);
}
// Process the packet internal if necessary
bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p)
{
bool ret = false;
if (e == NULL || p == NULL)
{
return false;
}
if (p->TypeL3 == L3_ARPV4)
{
// ARP processing
ARPV4_HEADER *arp = p->L3.ARPv4Header;
if (Endian16(arp->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
Endian16(arp->ProtocolType) == MAC_PROTO_IPV4 &&
arp->HardwareSize == 6 && arp->ProtocolType == 4)
{
if (IPToUINT(&e->MyIP) == arp->TargetIP)
{
if (Endian16(arp->Operation) == ARP_OPERATION_REQUEST)
{
ARPV4_HEADER r;
Zero(&r, sizeof(r));
r.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
r.ProtocolType = Endian16(MAC_PROTO_IPV4);
r.HardwareSize = 6;
r.ProtocolSize = 4;
r.Operation = Endian16(ARP_OPERATION_RESPONSE);
Copy(r.SrcAddress, e->RawIpMyMacAddr, 6);
Copy(r.TargetAddress, arp->SrcAddress, 6);
r.SrcIP = IPToUINT(&e->MyIP);
r.TargetIP = arp->SrcIP;
EthSendIpPacketInnerIpRaw(e, &r, sizeof(ARPV4_HEADER), MAC_PROTO_ARPV4);
}
}
}
}
else if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
{
// DHCP processing
DHCPV4_HEADER *dhcp;
UCHAR *data;
UINT size;
UINT dhcp_header_size;
UINT dhcp_data_offset;
UINT tran_id;
UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
bool ok;
DHCP_OPTION_LIST *opt;
dhcp = p->L7.DHCPv4Header;
tran_id = Endian32(dhcp->TransactionId);
// Get the DHCP data and size
dhcp_header_size = sizeof(DHCPV4_HEADER);
dhcp_data_offset = (UINT)(((UCHAR *)p->L7.DHCPv4Header) - ((UCHAR *)p->MacHeader) + dhcp_header_size);
data = ((UCHAR *)dhcp) + dhcp_header_size;
size = p->PacketSize - dhcp_data_offset;
if (dhcp_header_size < 5)
{
// Data size is invalid
return false;
}
// Search for Magic Cookie
ok = false;
while (size >= 5)
{
if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
{
// Found
data += 4;
size -= 4;
ok = true;
break;
}
data++;
size--;
}
if (ok == false)
{
// The packet is invalid
return false;
}
// Parse DHCP options list
opt = ParseDhcpOptionList(data, size);
if (opt == NULL)
{
// The packet is invalid
return false;
}
if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST || opt->Opcode == DHCP_INFORM))
{
// Operate as the server
UINT ip = IPToUINT(&e->YourIP);
if (ip != 0 || opt->Opcode == DHCP_INFORM)
{
// Respond if there is providable IP address
DHCP_OPTION_LIST ret;
LIST *o;
UINT hw_type;
UINT hw_addr_size;
UINT new_ip = ip;
IP default_dns;
Zero(&default_dns, sizeof(default_dns));
Zero(&ret, sizeof(ret));
ret.Opcode = (opt->Opcode == DHCP_DISCOVER ? DHCP_OFFER : DHCP_ACK);
ret.ServerAddress = IPToUINT(&e->MyIP);
ret.LeaseTime = 3600;
if (opt->Opcode == DHCP_INFORM)
{
ret.LeaseTime = 0;
}
ret.SubnetMask = SetIP32(255, 255, 255, 252);
if (UnixGetDefaultDns(&default_dns) && IsZeroIp(&default_dns) == false)
{
ret.DnsServer = IPToUINT(&default_dns);
ret.DnsServer2 = SetIP32(8, 8, 8, 8);
}
else
{
ret.DnsServer = SetIP32(8, 8, 8, 8);
ret.DnsServer2 = SetIP32(8, 8, 4, 4);
}
ret.Gateway = IPToUINT(&e->MyIP);
if (opt->Opcode != DHCP_INFORM)
{
char client_mac[MAX_SIZE];
char client_ip[64];
IP ips;
BinToStr(client_mac, sizeof(client_mac), p->MacAddressSrc, 6);
UINTToIP(&ips, ip);
IPToStr(client_ip, sizeof(client_ip), &ips);
Debug("IP_RAW: DHCP %s : %s given %s\n",
ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
client_mac, client_ip);
}
// Build a DHCP option
o = BuildDhcpOption(&ret);
if (o != NULL)
{
BUF *b = BuildDhcpOptionsBuf(o);
if (b != NULL)
{
UINT dest_ip = p->L3.IPv4Header->SrcIP;
UINT blank_size = 128 + 64;
UINT dhcp_packet_size;
UINT magic = Endian32(DHCP_MAGIC_COOKIE);
DHCPV4_HEADER *dhcp;
void *magic_cookie_addr;
void *buffer_addr;
if (dest_ip == 0)
{
dest_ip = 0xffffffff;
}
// Calculate the DHCP packet size
dhcp_packet_size = blank_size + sizeof(DHCPV4_HEADER) + sizeof(magic) + b->Size;
if (dhcp_packet_size < DHCP_MIN_SIZE)
{
// Padding
dhcp_packet_size = DHCP_MIN_SIZE;
}
// Create a header
dhcp = ZeroMalloc(dhcp_packet_size);
dhcp->OpCode = 2;
dhcp->HardwareType = hw_type;
dhcp->HardwareAddressSize = hw_addr_size;
dhcp->Hops = 0;
dhcp->TransactionId = Endian32(tran_id);
dhcp->Seconds = 0;
dhcp->Flags = 0;
dhcp->YourIP = new_ip;
dhcp->ServerIP = IPToUINT(&e->MyIP);
Copy(dhcp->ClientMacAddress, p->MacAddressSrc, 6);
// Calculate the address
magic_cookie_addr = (((UCHAR *)dhcp) + sizeof(DHCPV4_HEADER) + blank_size);
buffer_addr = ((UCHAR *)magic_cookie_addr) + sizeof(magic);
// Magic Cookie
Copy(magic_cookie_addr, &magic, sizeof(magic));
// Buffer
Copy(buffer_addr, b->Buf, b->Size);
if (true)
{
UCHAR *data = ZeroMalloc(sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size);
IPV4_HEADER *ipv4 = (IPV4_HEADER *)(data);
UDP_HEADER *udp = (UDP_HEADER *)(data + sizeof(IPV4_HEADER));
Copy(data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), dhcp, dhcp_packet_size);
IPV4_SET_VERSION(ipv4, 4);
IPV4_SET_HEADER_LEN(ipv4, 5);
ipv4->TotalLength = Endian16(sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size);
ipv4->TimeToLive = 63;
ipv4->Protocol = IP_PROTO_UDP;
ipv4->SrcIP = IPToUINT(&e->MyIP);
ipv4->DstIP = dest_ip;
ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
udp->SrcPort = Endian16(NAT_DHCP_SERVER_PORT);
udp->DstPort = Endian16(NAT_DHCP_CLIENT_PORT);
udp->PacketLength = Endian16(sizeof(UDP_HEADER) + dhcp_packet_size);
udp->Checksum = CalcChecksumForIPv4(ipv4->SrcIP, ipv4->DstIP, IP_PROTO_UDP,
dhcp, dhcp_packet_size, 0);
if (udp->Checksum == 0)
{
udp->Checksum = 0xffff;
}
EthSendIpPacketInnerIpRaw(e, data, sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size, MAC_PROTO_IPV4);
Free(data);
}
// Release the memory
Free(dhcp);
FreeBuf(b);
}
FreeDhcpOptions(o);
}
}
}
Free(opt);
}
return ret;
}
// Send an IP raw packet
void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size)
{
PKT *p;
// Validate arguments
if (e == NULL || data == NULL)
{
return;
}
if (size < 14 || size > MAX_PACKET_SIZE || e->RawIp_HasError)
{
Free(data);
return;
}
p = ParsePacket(data, size);
if (p->BroadcastPacket || Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) == 0)
{
if (IsValidUnicastMacAddress(p->MacAddressSrc))
{
Copy(e->RawIpYourMacAddr, p->MacAddressSrc, 6);
}
}
if (IsZero(e->RawIpYourMacAddr, 6) || IsValidUnicastMacAddress(p->MacAddressSrc) == false ||
(p->BroadcastPacket == false && Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) != 0))
{
Free(data);
FreePacket(p);
return;
}
if (p != NULL)
{
SOCK *s = NULL;
if (p->TypeL3 == L3_IPV4)
{
if (p->TypeL4 == L4_TCP)
{
if (IsZeroIP(&e->MyPhysicalIP) == false)
{
s = e->RawTcp;
}
}
else if (p->TypeL4 == L4_UDP)
{
if (EthProcessIpPacketInnerIpRaw(e, p) == false)
{
s = e->RawUdp;
}
}
else if (p->TypeL4 == L4_ICMPV4)
{
if (IsZeroIP(&e->MyPhysicalIP) == false)
{
s = e->RawIcmp;
}
}
else if (p->TypeL4 == L4_FRAGMENT)
{
if (IsZeroIP(&e->MyPhysicalIP) == false)
{
s = e->RawIcmp;
}
}
}
else if (p->TypeL3 == L3_ARPV4)
{
EthProcessIpPacketInnerIpRaw(e, p);
}
if (s != NULL && p->L3.IPv4Header->DstIP != 0xffffffff && p->BroadcastPacket == false &&
p->L3.IPv4Header->SrcIP == IPToUINT(&e->YourIP))
{
UCHAR *send_data = p->IPv4PayloadData;
UCHAR *head = p->PacketData;
UINT remove_header_size = (UINT)(send_data - head);
if (p->PacketSize > remove_header_size)
{
IP dest;
UINT send_data_size = p->PacketSize - remove_header_size;
// checksum
if (p->TypeL4 == L4_UDP)
{
p->L4.UDPHeader->Checksum = 0;
}
else if (p->TypeL4 == L4_TCP)
{
p->L4.TCPHeader->Checksum = 0;
p->L4.TCPHeader->Checksum = CalcChecksumForIPv4(IPToUINT(&e->MyPhysicalIP),
p->L3.IPv4Header->DstIP, IP_PROTO_TCP,
p->L4.TCPHeader, p->IPv4PayloadSize, 0);
}
UINTToIP(&dest, p->L3.IPv4Header->DstIP);
if (s->RawIP_HeaderIncludeFlag == false)
{
SendTo(s, &dest, 0, send_data, send_data_size);
}
else
{
IPV4_HEADER *ip = p->L3.IPv4Header;
ip->SrcIP = IPToUINT(&e->MyPhysicalIP);
ip->Checksum = 0;
ip->Checksum = IpChecksum(ip, IPV4_GET_HEADER_LEN(ip) * 4);
SendTo(s, &dest, 0, ip, ((UCHAR *)p->PacketData - (UCHAR *)ip) + p->PacketSize);
}
}
}
FreePacket(p);
}
Free(data);
}
#endif // BRIDGE_C
+23 -1
View File
@@ -162,6 +162,19 @@ struct ETH
VLAN *Tap; // tap
bool Linux_IsAuxDataSupported; // Is PACKET_AUXDATA supported
bool IsRawIpMode; // RAW IP mode
SOCK *RawTcp, *RawUdp, *RawIcmp; // RAW sockets
bool RawIp_HasError;
UCHAR RawIpMyMacAddr[6];
UCHAR RawIpYourMacAddr[6];
IP MyIP;
IP YourIP;
QUEUE *RawIpSendQueue;
IP MyPhysicalIP;
IP MyPhysicalIPForce;
UCHAR *RawIP_TmpBuffer;
UINT RawIP_TmpBufferSize;
};
#if defined( BRIDGE_BPF ) || defined( BRIDGE_PCAP )
@@ -180,7 +193,8 @@ bool IsEthSupportedLinux();
bool IsEthSupportedSolaris();
bool IsEthSupportedPcap();
TOKEN_LIST *GetEthList();
TOKEN_LIST *GetEthListLinux();
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip);
TOKEN_LIST *GetEthListLinux(bool enum_normal, bool enum_rawip);
TOKEN_LIST *GetEthListSolaris();
TOKEN_LIST *GetEthListPcap();
ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr);
@@ -203,6 +217,14 @@ bool EthIsChangeMtuSupported(ETH *e);
bool EthGetInterfaceDescriptionUnix(char *name, char *str, UINT size);
bool EthIsInterfaceDescriptionSupportedUnix();
ETH *OpenEthLinuxIpRaw();
void CloseEthLinuxIpRaw(ETH *e);
UINT EthGetPacketLinuxIpRaw(ETH *e, void **data);
UINT EthGetPacketLinuxIpRawForSock(ETH *e, void **data, SOCK *s, UINT proto);
void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size);
bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p);
void EthSendIpPacketInnerIpRaw(ETH *e, void *data, UINT size, USHORT protocol);
#ifdef UNIX_SOLARIS
// Function prototype for Solaris
bool DlipAttatchRequest(int fd, UINT devid);
+8 -3
View File
@@ -1356,9 +1356,9 @@ TOKEN_LIST *GetEthList()
{
UINT v;
return GetEthListEx(&v);
return GetEthListEx(&v, true, false);
}
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden)
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip)
{
TOKEN_LIST *ret;
UINT i;
@@ -1371,6 +1371,11 @@ TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden)
return NULL;
}
if (enum_normal == false)
{
return NullToken();
}
if (total_num_including_hidden == NULL)
{
total_num_including_hidden = &dummy_int;
@@ -2139,7 +2144,7 @@ RELEASE:
return false;
}
o = GetEthListEx(&total_num);
o = GetEthListEx(&total_num, true, false);
if (o == NULL || total_num == 0)
{
FreeToken(o);
+7 -1
View File
@@ -213,6 +213,12 @@ struct ETH
SU *Su; // SeLow handle
SU_ADAPTER *SuAdapter; // SeLow adapter handle
// Unused
bool IsRawIpMode; // RAW IP mode
UCHAR RawIpMyMacAddr[6];
UCHAR RawIpYourMacAddr[6];
IP MyPhysicalIPForce;
};
// Function prototype
@@ -221,7 +227,7 @@ void FreeEth();
bool IsEthSupported();
bool IsEthSupportedInner();
TOKEN_LIST *GetEthList();
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden);
TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip);
ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr);
ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr);
void CloseEth(ETH *e);
+28
View File
@@ -118,6 +118,34 @@ static UINT init_cedar_counter = 0;
static REF *cedar_log_ref = NULL;
static LOG *cedar_log;
// Check whether there is any EAP-enabled RADIUS configuration
bool CedarIsThereAnyEapEnabledRadiusConfig(CEDAR *c)
{
bool ret = false;
UINT i;
if (c == NULL)
{
return false;
}
LockHubList(c);
{
for (i = 0;i < LIST_NUM(c->HubList);i++)
{
HUB *hub = LIST_DATA(c->HubList, i);
if (hub->RadiusConvertAllMsChapv2AuthRequestToEap)
{
ret = true;
break;
}
}
}
UnlockHubList(c);
return ret;
}
// Get build date of current code
UINT64 GetCurrentBuildDate()
{
+7 -6
View File
@@ -138,7 +138,7 @@
#define CEDAR_VER 419
// Build Number
#define CEDAR_BUILD 9578
#define CEDAR_BUILD 9582
// Beta number
//#define BETA_NUMBER 3
@@ -153,16 +153,16 @@
// Specify the location to build
#ifndef BUILD_PLACE
#define BUILD_PLACE "pc25"
#define BUILD_PLACE "pc30"
#endif // BUILD_PLACE
// Specifies the build date
#define BUILD_DATE_Y 2015
#define BUILD_DATE_M 9
#define BUILD_DATE_D 15
#define BUILD_DATE_M 10
#define BUILD_DATE_D 6
#define BUILD_DATE_HO 14
#define BUILD_DATE_MI 39
#define BUILD_DATE_SE 35
#define BUILD_DATE_MI 56
#define BUILD_DATE_SE 30
// Tolerable time difference
#define ALLOW_TIMESTAMP_DIFF (UINT64)(3 * 24 * 60 * 60 * 1000)
@@ -1259,6 +1259,7 @@ UINT CedarGetQueueBudgetConsuming(CEDAR *c);
UINT CedarGetFifoBudgetConsuming(CEDAR *c);
UINT CedarGetQueueBudgetBalance(CEDAR *c);
UINT CedarGetFifoBudgetBalance(CEDAR *c);
bool CedarIsThereAnyEapEnabledRadiusConfig(CEDAR *c);
+12
View File
@@ -142,6 +142,16 @@ typedef struct AUTHNT AUTHNT;
// ==============================================================
typedef struct RADIUS_LOGIN_OPTION RADIUS_LOGIN_OPTION;
typedef struct RADIUS_PACKET RADIUS_PACKET;
typedef struct RADIUS_AVP RADIUS_AVP;
typedef struct EAP_CLIENT EAP_CLIENT;
typedef struct EAP_MESSAGE EAP_MESSAGE;
typedef struct EAP_MSCHAPV2_GENERAL EAP_MSCHAPV2_GENERAL;
typedef struct EAP_MSCHAPV2_CHALLENGE EAP_MSCHAPV2_CHALLENGE;
typedef struct EAP_MSCHAPV2_RESPONSE EAP_MSCHAPV2_RESPONSE;
typedef struct EAP_MSCHAPV2_SUCCESS_SERVER EAP_MSCHAPV2_SUCCESS_SERVER;
typedef struct EAP_MSCHAPV2_SUCCESS_CLIENT EAP_MSCHAPV2_SUCCESS_CLIENT;
typedef struct EAP_PEAP EAP_PEAP;
// ==============================================================
@@ -738,6 +748,8 @@ typedef struct MIRROR_SERVER MIRROR_SERVER;
// ==============================================================
typedef struct NATIVE_STACK NATIVE_STACK;
typedef struct IPTABLES_STATE IPTABLES_STATE;
typedef struct IPTABLES_ENTRY IPTABLES_ENTRY;
// ==============================================================
+1
View File
@@ -18309,6 +18309,7 @@ UINT PsSecureNatStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
CtInsert(ct, _UU("NM_STATUS_DHCP"), tmp);
CtInsert(ct, _UU("SM_SNAT_IS_KERNEL"), t.IsKernelMode ? _UU("SEC_YES") : _UU("SEC_NO"));
CtInsert(ct, _UU("SM_SNAT_IS_RAW"), t.IsRawIpMode ? _UU("SEC_YES") : _UU("SEC_NO"));
CtFree(ct, c);
}
+101
View File
@@ -166,6 +166,103 @@ ADMIN_OPTION admin_options[] =
UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION);
// Create an EAP client for the specified Virtual Hub
EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username)
{
HUB *hub = NULL;
EAP_CLIENT *ret = NULL;
char radius_servers[MAX_PATH] = {0};
UINT radius_port = 0;
UINT radius_retry_interval = 0;
char radius_secret[MAX_PATH] = {0};
char radius_suffix_filter[MAX_PATH] = {0};
if (cedar == NULL || hubname == NULL || client_ip_str == NULL || username == NULL)
{
return NULL;
}
// Find the Virtual Hub
LockHubList(cedar);
{
hub = GetHub(cedar, hubname);
}
UnlockHubList(cedar);
if (hub != NULL)
{
if (GetRadiusServerEx2(hub, radius_servers, sizeof(radius_servers), &radius_port, radius_secret,
sizeof(radius_secret), &radius_retry_interval, radius_suffix_filter, sizeof(radius_suffix_filter)))
{
bool use_peap = hub->RadiusUsePeapInsteadOfEap;
if (IsEmptyStr(radius_suffix_filter) || EndWith(username, radius_suffix_filter))
{
TOKEN_LIST *radius_servers_list = ParseToken(radius_servers, " ,;\t");
if (radius_servers_list != NULL && radius_servers_list->NumTokens >= 1)
{
// Try for each of RADIUS servers
UINT i;
bool finish = false;
for (i = 0;i < radius_servers_list->NumTokens;i++)
{
EAP_CLIENT *eap;
IP ip;
if (GetIP(&ip, radius_servers_list->Token[i]))
{
eap = NewEapClient(&ip, radius_port, radius_secret, radius_retry_interval,
RADIUS_INITIAL_EAP_TIMEOUT, client_ip_str, username);
if (eap != NULL)
{
if (use_peap == false)
{
// EAP
if (EapClientSendMsChapv2AuthRequest(eap))
{
eap->GiveupTimeout = RADIUS_RETRY_TIMEOUT;
ret = eap;
finish = true;
}
}
else
{
// PEAP
if (PeapClientSendMsChapv2AuthRequest(eap))
{
eap->GiveupTimeout = RADIUS_RETRY_TIMEOUT;
ret = eap;
finish = true;
}
}
if (finish == false)
{
ReleaseEapClient(eap);
}
}
}
if (finish)
{
break;
}
}
}
FreeToken(radius_servers_list);
}
}
}
ReleaseHub(hub);
return ret;
}
// Create a user list
LIST *NewUserList()
{
@@ -587,6 +684,7 @@ void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
GetHubAdminOptionDataAndSet(ao, "SecureNAT_MaxIcmpSessionsPerIp", &o->SecureNAT_MaxIcmpSessionsPerIp);
GetHubAdminOptionDataAndSet(ao, "AccessListIncludeFileCacheLifetime", &o->AccessListIncludeFileCacheLifetime);
GetHubAdminOptionDataAndSet(ao, "DisableKernelModeSecureNAT", &o->DisableKernelModeSecureNAT);
GetHubAdminOptionDataAndSet(ao, "DisableIpRawModeSecureNAT", &o->DisableIpRawModeSecureNAT);
GetHubAdminOptionDataAndSet(ao, "DisableUserModeSecureNAT", &o->DisableUserModeSecureNAT);
GetHubAdminOptionDataAndSet(ao, "DisableCheckMacOnLocalBridge", &o->DisableCheckMacOnLocalBridge);
GetHubAdminOptionDataAndSet(ao, "DisableCorrectIpOffloadChecksum", &o->DisableCorrectIpOffloadChecksum);
@@ -598,6 +696,7 @@ void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
GetHubAdminOptionDataAndSet(ao, "SuppressClientUpdateNotification", &o->SuppressClientUpdateNotification);
GetHubAdminOptionDataAndSet(ao, "FloodingSendQueueBufferQuota", &o->FloodingSendQueueBufferQuota);
GetHubAdminOptionDataAndSet(ao, "AssignVLanIdByRadiusAttribute", &o->AssignVLanIdByRadiusAttribute);
GetHubAdminOptionDataAndSet(ao, "DenyAllRadiusLoginWithNoVlanAssign", &o->DenyAllRadiusLoginWithNoVlanAssign);
GetHubAdminOptionDataAndSet(ao, "SecureNAT_RandomizeAssignIp", &o->SecureNAT_RandomizeAssignIp);
GetHubAdminOptionDataAndSet(ao, "DetectDormantSessionInterval", &o->DetectDormantSessionInterval);
GetHubAdminOptionDataAndSet(ao, "NoPhysicalIPOnPacketLog", &o->NoPhysicalIPOnPacketLog);
@@ -656,6 +755,7 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
Add(aol, NewAdminOption("SecureNAT_MaxIcmpSessionsPerIp", o->SecureNAT_MaxIcmpSessionsPerIp));
Add(aol, NewAdminOption("AccessListIncludeFileCacheLifetime", o->AccessListIncludeFileCacheLifetime));
Add(aol, NewAdminOption("DisableKernelModeSecureNAT", o->DisableKernelModeSecureNAT));
Add(aol, NewAdminOption("DisableIpRawModeSecureNAT", o->DisableIpRawModeSecureNAT));
Add(aol, NewAdminOption("DisableUserModeSecureNAT", o->DisableUserModeSecureNAT));
Add(aol, NewAdminOption("DisableCheckMacOnLocalBridge", o->DisableCheckMacOnLocalBridge));
Add(aol, NewAdminOption("DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum));
@@ -667,6 +767,7 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
Add(aol, NewAdminOption("SuppressClientUpdateNotification", o->SuppressClientUpdateNotification));
Add(aol, NewAdminOption("FloodingSendQueueBufferQuota", o->FloodingSendQueueBufferQuota));
Add(aol, NewAdminOption("AssignVLanIdByRadiusAttribute", o->AssignVLanIdByRadiusAttribute));
Add(aol, NewAdminOption("DenyAllRadiusLoginWithNoVlanAssign", o->DenyAllRadiusLoginWithNoVlanAssign));
Add(aol, NewAdminOption("SecureNAT_RandomizeAssignIp", o->SecureNAT_RandomizeAssignIp));
Add(aol, NewAdminOption("DetectDormantSessionInterval", o->DetectDormantSessionInterval));
Add(aol, NewAdminOption("NoPhysicalIPOnPacketLog", o->NoPhysicalIPOnPacketLog));
+5
View File
@@ -265,6 +265,7 @@ struct HUB_OPTION
UINT SecureNAT_MaxIcmpSessionsPerIp; // Maximum number of ICMP sessions per IP address
UINT AccessListIncludeFileCacheLifetime; // Expiration of the access list external file (in seconds)
bool DisableKernelModeSecureNAT; // Disable the kernel mode NAT
bool DisableIpRawModeSecureNAT; // Disable the IP Raw Mode NAT
bool DisableUserModeSecureNAT; // Disable the user mode NAT
bool DisableCheckMacOnLocalBridge; // Disable the MAC address verification in local bridge
bool DisableCorrectIpOffloadChecksum; // Disable the correction of checksum that is IP-Offloaded
@@ -276,6 +277,7 @@ struct HUB_OPTION
bool SuppressClientUpdateNotification; // Suppress the update notification function on the VPN Client
UINT FloodingSendQueueBufferQuota; // The global quota of send queues of flooding packets
bool AssignVLanIdByRadiusAttribute; // Assign the VLAN ID for the VPN session, by the attribute value of RADIUS
bool DenyAllRadiusLoginWithNoVlanAssign; // Deny all RADIUS login with no VLAN ID assigned
bool SecureNAT_RandomizeAssignIp; // Randomize the assignment IP address for new DHCP client
UINT DetectDormantSessionInterval; // Interval (seconds) threshold to detect a dormant VPN session
bool NoPhysicalIPOnPacketLog; // Disable saving physical IP address on the packet log
@@ -434,6 +436,8 @@ struct HUB
UINT RadiusRetryInterval; // Radius retry interval
BUF *RadiusSecret; // Radius shared key
char RadiusSuffixFilter[MAX_SIZE]; // Radius suffix filter
bool RadiusConvertAllMsChapv2AuthRequestToEap; // Convert all MS-CHAPv2 auth request to EAP
bool RadiusUsePeapInsteadOfEap; // Use PEAP instead of EAP
volatile bool Halt; // Halting flag
bool Offline; // Offline
bool BeingOffline; // Be Doing Offline
@@ -636,6 +640,7 @@ void CalcTrafficDiff(TRAFFIC *diff, TRAFFIC *old, TRAFFIC *current);
bool CheckMaxLoggedPacketsPerMinute(SESSION *s, UINT max_packets, UINT64 now);
void VgsSetUserAgentValue(char *str);
void VgsSetEmbTag(bool b);
EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username);
#endif // HUB_H
+1 -1
View File
@@ -170,7 +170,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p)
&s->ClientIP, s->ClientPort,
&s->ServerIP, s->ServerPort,
tmp,
s->CryptName, true, mss);
s->CryptName, true, mss, NULL);
if (ipc != NULL)
{
+15 -1
View File
@@ -113,6 +113,7 @@
#include "CedarPch.h"
//#define RAW_DEBUG
// Processing of IKE received packet
void ProcIKEPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
@@ -753,7 +754,7 @@ void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
// Transport mode
if (next_header == IP_PROTO_UDP)
{
if (ike->IPsec->Services.L2TP_IPsec)
if (ike->IPsec->Services.L2TP_IPsec || ike->IPsec->Services.EtherIP_IPsec)
{
// An UDP packet has been received
ProcIPsecUdpPacketRecv(ike, c, dec_data, dec_size);
@@ -791,6 +792,19 @@ void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p)
if (ipsec_sa->PairIPsecSa != NULL)
{
c->CurrentIpSecSaSend = ipsec_sa->PairIPsecSa;
if (p->DestPort == IPSEC_PORT_IPSEC_ESP_UDP)
{
IPSECSA *send_sa = c->CurrentIpSecSaSend;
if (send_sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_TUNNEL)
{
send_sa->TransformSetting.CapsuleMode = IKE_P2_CAPSULE_NAT_TUNNEL_1;
}
else if (send_sa->TransformSetting.CapsuleMode == IKE_P2_CAPSULE_TRANSPORT)
{
send_sa->TransformSetting.CapsuleMode = IKE_P2_CAPSULE_NAT_TRANSPORT_1;
}
}
}
c->LastCommTick = ike->Now;
ipsec_sa->LastCommTick = ike->Now;
+21 -5
View File
@@ -133,20 +133,27 @@ bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *pa
t = ParseTokenWithNullStr(password, ":");
if (t->NumTokens == 5)
if (t->NumTokens == 6)
{
BUF *b1, *b2, *b3;
BUF *b1, *b2, *b3, *b4;
b1 = StrToBin(t->Token[2]);
b2 = StrToBin(t->Token[3]);
b3 = StrToBin(t->Token[4]);
b4 = StrToBin(t->Token[5]);
if (IsEmptyStr(t->Token[1]) == false && b1->Size == 16 && b2->Size == 16 && b3->Size == 24)
if (IsEmptyStr(t->Token[1]) == false && b1->Size == 16 && b2->Size == 16 && b3->Size == 24
&& b4->Size == 8)
{
UINT64 eap_client_ptr = 0;
StrCpy(d->MsChapV2_PPPUsername, sizeof(d->MsChapV2_PPPUsername), t->Token[1]);
Copy(d->MsChapV2_ServerChallenge, b1->Buf, 16);
Copy(d->MsChapV2_ClientChallenge, b2->Buf, 16);
Copy(d->MsChapV2_ClientResponse, b3->Buf, 24);
Copy(&eap_client_ptr, b4->Buf, 8);
d->MsChapV2_EapClient = (EAP_CLIENT *)eap_client_ptr;
ret = true;
}
@@ -154,6 +161,7 @@ bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *pa
FreeBuf(b1);
FreeBuf(b2);
FreeBuf(b3);
FreeBuf(b4);
}
FreeToken(t);
@@ -315,7 +323,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
param->UserName, param->Password, error_code, &param->ClientIp,
param->ClientPort, &param->ServerIp, param->ServerPort,
param->ClientHostname, param->CryptName,
param->BridgeMode, param->Mss);
param->BridgeMode, param->Mss, NULL);
return ipc;
}
@@ -324,7 +332,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
char *client_hostname, char *crypt_name,
bool bridge_mode, UINT mss)
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client)
{
IPC *ipc;
UINT dummy_int = 0;
@@ -431,6 +439,14 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
PackAddBool(p, "require_monitor_mode", false);
PackAddBool(p, "qos", false);
if (eap_client != NULL)
{
UINT64 ptr = (UINT64)eap_client;
PackAddInt64(p, "release_me_eap_client", ptr);
AddRef(eap_client->Ref);
}
// Unique ID is determined by the sum of the connecting client IP address and the client_name
b = NewBuf();
WriteBuf(b, client_ip, sizeof(IP));
+2 -1
View File
@@ -218,12 +218,13 @@ struct IPC_MSCHAP_V2_AUTHINFO
UCHAR MsChapV2_ServerChallenge[16]; // MS-CHAPv2 Server Challenge
UCHAR MsChapV2_ClientChallenge[16]; // MS-CHAPv2 Client Challenge
UCHAR MsChapV2_ClientResponse[24]; // MS-CHAPv2 Client Response
EAP_CLIENT *MsChapV2_EapClient; // EAP client
};
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
char *client_hostname, char *crypt_name,
bool bridge_mode, UINT mss);
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client);
IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code);
IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address);
void FreeIPC(IPC *ipc);
+192 -38
View File
@@ -180,7 +180,7 @@ void SendL2TPControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id, L
p->Nr = t->LastNr + 1;
buf = BuildL2TPPacketData(p);
buf = BuildL2TPPacketData(p, t);
q = ZeroMalloc(sizeof(L2TP_QUEUE));
q->Buf = buf;
@@ -239,15 +239,33 @@ void SendL2TPDataPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s, void
else
{
// L2TPv3
buf_size = 4 + size;
buf = Malloc(buf_size);
if (t->IsYamahaV3 == false)
{
buf_size = 4 + size;
buf = Malloc(buf_size);
WRITE_UINT(buf, s->SessionId1);
WRITE_UINT(buf, s->SessionId1);
Copy(buf + 4, data, size);
Copy(buf + 4, data, size);
// Transmission
p = NewUdpPacket(&t->ServerIp, IPSEC_PORT_L2TPV3_VIRTUAL, &t->ClientIp, IPSEC_PORT_L2TPV3_VIRTUAL, buf, buf_size);
// Transmission
p = NewUdpPacket(&t->ServerIp, IPSEC_PORT_L2TPV3_VIRTUAL, &t->ClientIp, IPSEC_PORT_L2TPV3_VIRTUAL, buf, buf_size);
}
else
{
UINT header = 0x00030000;
buf_size = 8 + size;
buf = Malloc(buf_size);
WRITE_UINT(buf, header);
WRITE_UINT(buf + 4, s->SessionId1);
Copy(buf + 8, data, size);
// Transmission
p = NewUdpPacket(&t->ServerIp, t->ServerPort, &t->ClientIp, t->ClientPort, buf, buf_size);
}
}
L2TPSendUDP(l2tp, p);
@@ -285,14 +303,14 @@ void L2TPSendUDP(L2TP_SERVER *l2tp, UDPPACKET *p)
}
// Build a L2TP packet
BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
BUF *BuildL2TPPacketData(L2TP_PACKET *pp, L2TP_TUNNEL *t)
{
BUF *ret;
UCHAR c;
USHORT us;
UINT ui;
// Validate arguments
if (pp == NULL)
if (pp == NULL || t == NULL)
{
return NULL;
}
@@ -322,9 +340,12 @@ BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
if (pp->Ver == 3)
{
// Zero as Session ID
ui = 0;
WriteBuf(ret, &ui, sizeof(UINT));
if (t->IsYamahaV3 == false)
{
// Zero as Session ID
ui = 0;
WriteBuf(ret, &ui, sizeof(UINT));
}
}
// Flags
@@ -339,6 +360,11 @@ BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
c |= L2TP_HEADER_BIT_OFFSET;
}
if (pp->IsControl == false && pp->Ver == 3 && t->IsYamahaV3)
{
c = 0;
}
WriteBuf(ret, &c, 1);
// Ver
@@ -356,6 +382,13 @@ BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
WriteBuf(ret, &us, sizeof(USHORT));
}
// Reserved
if (pp->IsControl == false && pp->Ver == 3 && t->IsYamahaV3)
{
us = 0;
WriteBuf(ret, &us, sizeof(USHORT));
}
// Tunnel ID
if (pp->Ver != 3)
{
@@ -387,9 +420,12 @@ BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
}
else
{
// Offset Size = 0
us = 0;
WriteBuf(ret, &us, sizeof(USHORT));
if (!(pp->IsControl == false && pp->Ver == 3 && t->IsYamahaV3))
{
// Offset Size = 0
us = 0;
WriteBuf(ret, &us, sizeof(USHORT));
}
}
if (pp->IsControl)
@@ -431,7 +467,8 @@ BUF *BuildL2TPPacketData(L2TP_PACKET *pp)
if (pp->IsControl)
{
// Update Length
WRITE_USHORT(((UCHAR *)ret->Buf) + 2 + (pp->Ver == 3 ? sizeof(UINT) : 0), (USHORT)(ret->Size - (pp->Ver == 3 ? sizeof(UINT) : 0)));
bool l2tpv3_non_yamaha = ((pp->Ver == 3) && (t->IsYamahaV3 == false));
WRITE_USHORT(((UCHAR *)ret->Buf) + 2 + (l2tpv3_non_yamaha ? sizeof(UINT) : 0), (USHORT)(ret->Size - (l2tpv3_non_yamaha ? sizeof(UINT) : 0)));
}
SeekBuf(ret, 0, 0);
@@ -446,6 +483,7 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
UCHAR *buf;
UINT size;
bool is_l2tpv3 = false;
bool is_l2tpv3_yamaha = false;
// Validate arguments
if (p == NULL)
{
@@ -456,17 +494,27 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
if (p->SrcPort == IPSEC_PORT_L2TPV3_VIRTUAL)
{
// It is L2TPv3
// L2TPv3 (Cisco)
is_l2tpv3 = true;
}
buf = p->Data;
size = p->Size;
if (is_l2tpv3)
if (size >= 2 && ((buf[1] & L2TP_HEADER_BIT_VER) == 3))
{
if (p->SrcPort != IPSEC_PORT_L2TPV3_VIRTUAL)
{
// L2TPv3 (YAMAHA)
is_l2tpv3 = true;
is_l2tpv3_yamaha = true;
}
}
if (is_l2tpv3 && (is_l2tpv3_yamaha == false))
{
// L2TPv3 (Cisco)
UINT session_id;
// In the case of L2TPv3
if (size < 4)
{
goto LABEL_ERROR;
@@ -590,6 +638,24 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
size = ret->Length - 4;
}
if (is_l2tpv3)
{
if (p->SrcPort != IPSEC_PORT_L2TPV3_VIRTUAL)
{
if (ret->IsControl == false)
{
// Reserved
if (size < 2)
{
goto LABEL_ERROR;
}
buf += 2;
size -= 2;
}
}
}
// Tunnel ID, Session ID
if (size < 4)
{
@@ -616,6 +682,11 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
// The session ID is not written in the header
ret->SessionId = 0;
if (ret->IsControl == false)
{
ret->SessionId = ret->TunnelId;
}
}
if (ret->HasSequence)
@@ -742,7 +813,7 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
ret->MessageType = READ_USHORT(a->Data);
}
if (ret->Ver == 3)
if (ret->Ver == 3 && ret->IsControl)
{
// Get the Remote Session ID in the case of L2TPv3
L2TP_AVP *a = GetAVPValue(ret, L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE);
@@ -752,6 +823,8 @@ L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p)
}
}
ret->IsYamahaV3 = is_l2tpv3_yamaha;
return ret;
LABEL_ERROR:
@@ -783,6 +856,22 @@ L2TP_AVP *GetAVPValueEx(L2TP_PACKET *p, UINT type, UINT vendor_id)
}
}
if (vendor_id == 0)
{
if (type == L2TP_AVP_TYPE_V3_TUNNEL_ID)
{
return GetAVPValueEx(p, L2TPV3_CISCO_AVP_TUNNEL_ID, L2TP_AVP_VENDOR_ID_CISCO);
}
else if (type == L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL)
{
return GetAVPValueEx(p, L2TPV3_CISCO_AVP_SESSION_ID_LOCAL, L2TP_AVP_VENDOR_ID_CISCO);
}
else if (type == L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE)
{
return GetAVPValueEx(p, L2TPV3_CISCO_AVP_SESSION_ID_REMOTE, L2TP_AVP_VENDOR_ID_CISCO);
}
}
return NULL;
}
@@ -899,6 +988,9 @@ L2TP_TUNNEL *NewL2TPTunnel(L2TP_SERVER *l2tp, L2TP_PACKET *p, UDPPACKET *udp)
{
t->IsCiscoV3 = true;
}
// L2TPv3 on YAMAHA
t->IsYamahaV3 = p->IsYamahaV3;
}
// Transmission queue
@@ -965,6 +1057,30 @@ L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClient(L2TP_SERVER *l2tp, IP *client_ip,
return NULL;
}
L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClientEx(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id, bool is_v3)
{
UINT i;
// Validate arguments
if (l2tp == NULL || client_ip == 0 || tunnel_id == 0)
{
return NULL;
}
for (i = 0;i < LIST_NUM(l2tp->TunnelList);i++)
{
L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i);
if (t->TunnelId1 == tunnel_id && CmpIpAddr(&t->ClientIp, client_ip) == 0)
{
if (EQUAL_BOOL(t->IsV3, is_v3))
{
return t;
}
}
}
return NULL;
}
// Create a new tunnel ID
UINT GenerateNewTunnelId(L2TP_SERVER *l2tp, IP *client_ip)
@@ -1179,14 +1295,23 @@ void L2TPProcessRecvControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_PACKET
if (s->IsV3)
{
// Pseudowire AVP
us = Endian16(s->PseudowireType);
Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_PW_TYPE, true, 0, &us, sizeof(USHORT)));
if (t->IsYamahaV3 == false)
{
// Pseudowire AVP
us = Endian16(s->PseudowireType);
Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_PW_TYPE, true, 0, &us, sizeof(USHORT)));
}
if (s->IsCiscoV3)
{
Add(pp->AvpList, NewAVP(L2TPV3_CISCO_AVP_PW_TYPE, true, L2TP_AVP_VENDOR_ID_CISCO, &us, sizeof(USHORT)));
}
if (t->IsYamahaV3)
{
us = Endian16(0x0003);
Add(pp->AvpList, NewAVP(L2TP_AVP_TYPE_V3_CIRCUIT_STATUS, true, 0, &us, sizeof(USHORT)));
}
}
SendL2TPControlPacket(l2tp, t, session_id, pp);
@@ -1563,18 +1688,21 @@ void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
// Respond with SCCEP to SCCRQ
pp2 = NewL2TPControlPacket(L2TP_MESSAGE_TYPE_SCCRP, t->IsV3);
// Protocol Version
protocol_version[0] = 1;
protocol_version[1] = 0;
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_PROTOCOL_VERSION, true, 0, protocol_version, sizeof(protocol_version)));
// Framing Capabilities
Zero(caps_data, sizeof(caps_data));
if (t->IsV3 == false)
if (t->IsYamahaV3 == false)
{
caps_data[3] = 3;
// Protocol Version
protocol_version[0] = 1;
protocol_version[1] = 0;
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_PROTOCOL_VERSION, true, 0, protocol_version, sizeof(protocol_version)));
// Framing Capabilities
Zero(caps_data, sizeof(caps_data));
if (t->IsV3 == false)
{
caps_data[3] = 3;
}
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_FRAME_CAP, false, 0, caps_data, sizeof(caps_data)));
}
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_FRAME_CAP, false, 0, caps_data, sizeof(caps_data)));
if (t->IsV3 == false)
{
@@ -1593,7 +1721,21 @@ void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_HOST_NAME, true, 0, hostname, StrLen(hostname)));
// Vendor Name
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_VENDOR_NAME, false, 0, L2TP_VENDOR_NAME, StrLen(L2TP_VENDOR_NAME)));
if (t->IsYamahaV3 == false)
{
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_VENDOR_NAME, false, 0, L2TP_VENDOR_NAME, StrLen(L2TP_VENDOR_NAME)));
}
else
{
char *yamaha_str = "YAMAHA Corporation";
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_VENDOR_NAME, false, 0, yamaha_str, StrLen(yamaha_str)));
}
if (t->IsYamahaV3)
{
UINT zero = 0;
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_V3_ROUTER_ID, true, 0, &zero, sizeof(UINT)));
}
// Assigned Tunnel ID
if (t->IsV3 == false)
@@ -1635,8 +1777,11 @@ void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
}
// Recv Window Size
us = Endian16(L2TP_WINDOW_SIZE);
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_RECV_WINDOW_SIZE, false, 0, &us, sizeof(USHORT)));
if (t->IsYamahaV3 == false)
{
us = Endian16(L2TP_WINDOW_SIZE);
Add(pp2->AvpList, NewAVP(L2TP_AVP_TYPE_RECV_WINDOW_SIZE, false, 0, &us, sizeof(USHORT)));
}
SendL2TPControlPacket(l2tp, t, 0, pp2);
@@ -1654,7 +1799,7 @@ void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
L2TP_TUNNEL *t = NULL;
L2TP_SESSION *l2tpv3_session = NULL;
if (pp->Ver != 3 || pp->IsControl)
if (pp->IsControl || pp->Ver != 3)
{
t = GetTunnelFromId(l2tp, &p->SrcIP, pp->TunnelId, pp->Ver == 3);
}
@@ -1767,6 +1912,15 @@ void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p)
}
}
}
else
{
// Reply ACK for already-received packets
if (pp->IsZLB == false)
{
// The packet other than ZLB is treated
t->StateChanged = true;
}
}
}
else
{
@@ -2373,7 +2527,7 @@ void L2TPProcessInterrupts(L2TP_SERVER *l2tp)
pp->TunnelId = t->TunnelId1;
pp->Ns = t->NextNs;
q->Buf = BuildL2TPPacketData(pp);
q->Buf = BuildL2TPPacketData(pp, t);
SendL2TPControlPacketMain(l2tp, t, q);
+5 -1
View File
@@ -189,6 +189,7 @@
#define L2TP_AVP_TYPE_V3_SESSION_ID_LOCAL 63 // Local Session ID
#define L2TP_AVP_TYPE_V3_SESSION_ID_REMOTE 64 // Remote Session ID
#define L2TP_AVP_TYPE_V3_PW_TYPE 68 // Pseudowire Type
#define L2TP_AVP_TYPE_V3_CIRCUIT_STATUS 71
// Message Type value
#define L2TP_MESSAGE_TYPE_SCCRQ 1 // Start-Control-Connection-Request
@@ -247,6 +248,7 @@ struct L2TP_PACKET
bool HasOffset; // Whether there is offset bit
bool IsPriority; // Whether priority packet
bool IsZLB; // Zero Length Bit
bool IsYamahaV3; // L2TPv3 on YAMAHA
UINT Ver; // Version
UINT Length; // Length
UINT TunnelId; // Tunnel ID
@@ -284,6 +286,7 @@ struct L2TP_TUNNEL
{
bool IsV3; // L2TPv3
bool IsCiscoV3; // L2TPv3 for Cisco
bool IsYamahaV3; // L2TPv3 for YAMAHA
IP ClientIp; // Client IP address
UINT ClientPort; // Client port number
IP ServerIp; // Server IP address
@@ -339,7 +342,7 @@ void FreeL2TPServer(L2TP_SERVER *l2tp);
void StopL2TPServer(L2TP_SERVER *l2tp, bool no_wait);
void ProcL2TPPacketRecv(L2TP_SERVER *l2tp, UDPPACKET *p);
L2TP_PACKET *ParseL2TPPacket(UDPPACKET *p);
BUF *BuildL2TPPacketData(L2TP_PACKET *pp);
BUF *BuildL2TPPacketData(L2TP_PACKET *pp, L2TP_TUNNEL *t);
L2TP_AVP *GetAVPValue(L2TP_PACKET *p, UINT type);
L2TP_AVP *GetAVPValueEx(L2TP_PACKET *p, UINT type, UINT vendor_id);
L2TP_TUNNEL *NewL2TPTunnel(L2TP_SERVER *l2tp, L2TP_PACKET *p, UDPPACKET *udp);
@@ -348,6 +351,7 @@ UINT GenerateNewTunnelIdEx(L2TP_SERVER *l2tp, IP *client_ip, bool is_32bit);
void FreeL2TPTunnel(L2TP_TUNNEL *t);
L2TP_TUNNEL *GetTunnelFromId(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id, bool is_v3);
L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClient(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id);
L2TP_TUNNEL *GetTunnelFromIdOfAssignedByClientEx(L2TP_SERVER *l2tp, IP *client_ip, UINT tunnel_id, bool is_v3);
void SendL2TPControlPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, UINT session_id, L2TP_PACKET *p);
void SendL2TPControlPacketMain(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_QUEUE *q);
void SendL2TPDataPacket(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s, void *data, UINT size);
+132 -10
View File
@@ -135,6 +135,8 @@ void PPPThread(THREAD *thread, void *param)
p->Mru1 = p->Mru2 = PPP_MRU_DEFAULT;
p->RecvPacketList = NewList(NULL);
p->MsChapV2_UseDoubleMsChapV2 = CedarIsThereAnyEapEnabledRadiusConfig(p->Cedar);
//// Link establishment phase
IPToStr(ipstr1, sizeof(ipstr1), &p->ClientIP);
IPToStr(ipstr2, sizeof(ipstr2), &p->ServerIP);
@@ -244,9 +246,96 @@ void PPPThread(THREAD *thread, void *param)
PPPContinueUntilFinishAllLCPOptionRequestsDetermined(p);
if (p->MsChapV2_UseDoubleMsChapV2)
{
// Use the double-MSCHAPv2 technieue
GetMachineHostName(machine_name, sizeof(machine_name));
MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
pp = ZeroMalloc(sizeof(PPP_PACKET));
pp->Protocol = PPP_PROTOCOL_CHAP;
pp->IsControl = true;
pp->Lcp = NewPPPLCP(PPP_CHAP_CODE_CHALLENGE, 99);
b = NewBuf();
WriteBufChar(b, 16);
WriteBuf(b, p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
WriteBuf(b, machine_name, StrLen(machine_name));
pp->Lcp->Data = Clone(b->Buf, b->Size);
pp->Lcp->DataSize = b->Size;
FreeBuf(b);
PPPSendPacket(p, pp);
pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false, true);
if (pp_ret != NULL)
{
// Extract the username from the first MS-CHAP v2 packet
if (pp_ret->Lcp != NULL && pp_ret->Lcp->DataSize >= 51)
{
BUF *b;
b = MemToBuf(pp_ret->Lcp->Data, pp_ret->Lcp->DataSize);
if (ReadBufChar(b) == 49)
{
UCHAR client_response_buffer[49];
char username_tmp[MAX_SIZE];
char id[MAX_SIZE];
char hub[MAX_SIZE];
char client_ip_tmp[256];
EAP_CLIENT *eap;
ETHERIP_ID d;
ReadBuf(b, client_response_buffer, 49);
Zero(username_tmp, sizeof(username_tmp));
ReadBuf(b, username_tmp, sizeof(username_tmp));
Debug("First MS-CHAPv2: id=%s\n", username_tmp);
Zero(id, sizeof(id));
Zero(hub, sizeof(hub));
// The user name is divided into the ID and the virtual HUB name
Zero(&d, sizeof(d));
PPPParseUsername(p->Cedar, username_tmp, &d);
StrCpy(id, sizeof(id), d.UserName);
StrCpy(hub, sizeof(hub), d.HubName);
Debug("First MS-CHAPv2: username=%s, hubname=%s\n", id, hub);
IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP);
eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id);
if (eap)
{
p->EapClient = eap;
}
}
FreeBuf(b);
}
FreePPPPacket(pp_ret);
}
FreePPPPacket(pp);
}
// Generate a Server Challenge packet of MS-CHAP v2
GetMachineHostName(machine_name, sizeof(machine_name));
MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
if (p->EapClient == NULL)
{
MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
}
else
{
Copy(p->MsChapV2_ServerChallenge, p->EapClient->MsChapV2Challenge.Chap_ChallengeValue, 16);
}
pp = ZeroMalloc(sizeof(PPP_PACKET));
pp->Protocol = PPP_PROTOCOL_CHAP;
@@ -264,7 +353,7 @@ void PPPThread(THREAD *thread, void *param)
PPPSendPacket(p, pp);
pp_ret_protocol = 0;
pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false);
pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false, false);
if (pp_ret != NULL)
{
@@ -565,7 +654,7 @@ bool PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION *p)
return false;
}
PPPRecvResponsePacket(p, NULL, PPP_PROTOCOL_LCP, &received_protocol, true);
PPPRecvResponsePacket(p, NULL, PPP_PROTOCOL_LCP, &received_protocol, true, false);
return p->ClientLCPOptionDetermined;
}
@@ -580,7 +669,7 @@ USHORT PPPContinueCurrentProtocolRequestListening(PPP_SESSION *p, USHORT protoco
return 0;
}
PPPRecvResponsePacket(p, NULL, protocol, &received_protocol, false);
PPPRecvResponsePacket(p, NULL, protocol, &received_protocol, false, false);
return received_protocol;
}
@@ -634,7 +723,7 @@ bool PPPSendRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c)
}
// Receive a corresponding PPP packet
pp2 = PPPRecvResponsePacket(p, pp, 0, NULL, false);
pp2 = PPPRecvResponsePacket(p, pp, 0, NULL, false, false);
if (pp2 != NULL)
{
@@ -880,8 +969,10 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
char server_challenge_hex[MAX_SIZE];
char client_challenge_hex[MAX_SIZE];
char client_response_hex[MAX_SIZE];
char eap_client_hex[64];
ETHERIP_ID d;
UINT error_code;
UINT64 eap_client_ptr = (UINT64)p->EapClient;
ReadBuf(b, client_response_buffer, 49);
@@ -913,18 +1004,21 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
p->MsChapV2_ClientChallenge, sizeof(p->MsChapV2_ClientChallenge));
BinToStr(client_response_hex, sizeof(client_response_hex),
p->MsChapV2_ClientResponse, sizeof(p->MsChapV2_ClientResponse));
BinToStr(eap_client_hex, sizeof(eap_client_hex),
&eap_client_ptr, 8);
Format(password, sizeof(password), "%s%s:%s:%s:%s",
Format(password, sizeof(password), "%s%s:%s:%s:%s:%s",
IPC_PASSWORD_MSCHAPV2_TAG,
username_tmp,
server_challenge_hex,
client_challenge_hex,
client_response_hex);
client_response_hex,
eap_client_hex);
// Attempt to connect with IPC
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
p->ClientHostname, p->CryptName, false, p->AdjustMss);
p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient);
if (ipc != NULL)
{
@@ -1057,7 +1151,7 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
p->ClientHostname, p->CryptName, false, p->AdjustMss);
p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL);
if (ipc != NULL)
{
@@ -1555,7 +1649,8 @@ bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip)
// (If req == NULL, process on that protocol while the protocol specified in expected_protocol have received.
//If other protocols has arrived, without further processing, and then store that packet in the session context once,
// return NULL by setting the received_protocol.)
PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked)
PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked,
bool return_mschapv2_response_with_no_processing)
{
UINT64 giveup_tick = Tick64() + (UINT64)PPP_PACKET_RECV_TIMEOUT;
UINT64 next_resend = Tick64() + (UINT64)PPP_PACKET_RESEND_INTERVAL;
@@ -1618,6 +1713,16 @@ PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expect
{
return pp;
}
if (return_mschapv2_response_with_no_processing)
{
// For the double-MSCHAPv2 technique
if (pp->IsControl && pp->Protocol == req->Protocol && pp->Lcp->Id == req->Lcp->Id &&
pp->Protocol == PPP_PROTOCOL_CHAP && PPP_PAP_CODE_IS_RESPONSE(pp->Lcp->Code))
{
return pp;
}
}
}
// Return a response immediately without processing if a protocol other than the expected received
@@ -2357,9 +2462,26 @@ void FreePPPSession(PPP_SESSION *p)
FreeIPC(p->Ipc);
}
PPPFreeEapClient(p);
Free(p);
}
// Free the associated EAP client
void PPPFreeEapClient(PPP_SESSION *p)
{
if (p == NULL)
{
return;
}
if (p->EapClient != NULL)
{
ReleaseEapClient(p->EapClient);
p->EapClient = NULL;
}
}
// Get the option value
PPP_OPTION *GetOptionValue(PPP_LCP *c, UCHAR type)
{
+6 -1
View File
@@ -284,6 +284,9 @@ struct PPP_SESSION
UCHAR MsChapV2_ClientResponse[24]; // MS-CHAPv2 Client Response
UCHAR MsChapV2_ServerResponse[20]; // MS-CHAPv2 Server Response
UINT MsChapV2_ErrorCode; // Authentication failure error code of MS-CHAPv2
bool MsChapV2_UseDoubleMsChapV2; // Use the double-MSCHAPv2 technieue
EAP_CLIENT *EapClient; // EAP client
};
// Function prototype
@@ -316,7 +319,8 @@ bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify);
bool PPPSendRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c);
USHORT PPPContinueCurrentProtocolRequestListening(PPP_SESSION *p, USHORT protocol);
bool PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION *p);
PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked);
PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked,
bool return_mschapv2_response_with_no_processing);
PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req);
void PPPSendEchoRequest(PPP_SESSION *p);
bool PPPParseUsername(CEDAR *cedar, char *src, ETHERIP_ID *dst);
@@ -331,6 +335,7 @@ void MsChapV2Client_GenerateResponse(UCHAR *dst, UCHAR *challenge8, UCHAR *nt_pa
void MsChapV2Server_GenerateResponse(UCHAR *dst, UCHAR *nt_password_hash_hash, UCHAR *client_response, UCHAR *challenge8);
bool MsChapV2VerityPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password);
char *MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO *d, LIST *password_list);
void PPPFreeEapClient(PPP_SESSION *p);
#endif // IPSEC_PPP_H
+1
View File
@@ -784,6 +784,7 @@ bool NmStatus(HWND hWnd, SM_SERVER *s, void *param)
LvInsertAdd(b, ICO_PROTOCOL_DHCP, NULL, 2, _UU("NM_STATUS_DHCP"), tmp);
LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_SNAT_IS_KERNEL"), t.IsKernelMode ? _UU("SEC_YES") : _UU("SEC_NO"));
LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_SNAT_IS_RAW"), t.IsRawIpMode ? _UU("SEC_YES") : _UU("SEC_NO"));
LvInsertEnd(b, hWnd, L_STATUS);
+3 -1
View File
@@ -596,7 +596,7 @@ UINT NtGetStatus(NAT *n, RPC_NAT_STATUS *t)
t->NumDhcpClients = LIST_NUM(v->DhcpLeaseList);
t->IsKernelMode = NnIsActive(v);
t->IsKernelMode = NnIsActiveEx(v, &t->IsRawIpMode);
}
UnlockVirtual(v);
}
@@ -1063,6 +1063,7 @@ void InRpcNatStatus(RPC_NAT_STATUS *t, PACK *p)
t->NumDnsSessions = PackGetInt(p, "NumDnsSessions");
t->NumDhcpClients = PackGetInt(p, "NumDhcpClients");
t->IsKernelMode = PackGetBool(p, "IsKernelMode");
t->IsRawIpMode = PackGetBool(p, "IsRawIpMode");
PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
}
void OutRpcNatStatus(PACK *p, RPC_NAT_STATUS *t)
@@ -1080,6 +1081,7 @@ void OutRpcNatStatus(PACK *p, RPC_NAT_STATUS *t)
PackAddInt(p, "NumDnsSessions", t->NumDnsSessions);
PackAddInt(p, "NumDhcpClients", t->NumDhcpClients);
PackAddBool(p, "IsKernelMode", t->IsKernelMode);
PackAddBool(p, "IsRawIpMode", t->IsRawIpMode);
}
void FreeRpcNatStatus(RPC_NAT_STATUS *t)
{
+1
View File
@@ -168,6 +168,7 @@ struct RPC_NAT_STATUS
UINT NumDnsSessions; // Number of DNS sessions
UINT NumDhcpClients; // Number of DHCP clients
bool IsKernelMode; // Whether kernel mode
bool IsRawIpMode; // Whether raw IP mode
};
// RPC_NAT_INFO *
+564 -6
View File
@@ -257,6 +257,109 @@ LABEL_RESTART:
Disconnect(a->Sock2);
}
// Start the iptables tracking
bool NsStartIpTablesTracking(NATIVE_STACK *a)
{
if (a->IpTablesThread != NULL)
{
return true;
}
a->IpTablesInitOk = false;
a->IpTablesHalt = false;
a->IpTablesHaltEvent = NewEvent();
a->IpTablesThread = NewThread(NsIpTablesThread, a);
WaitThreadInit(a->IpTablesThread);
return a->IpTablesInitOk;
}
// iptables thread
void NsIpTablesThread(THREAD *thread, void *param)
{
IPTABLES_STATE *state;
NATIVE_STACK *s;
UINT counter = 0;
BUF *seed_buf;
char exe_name[MAX_PATH];
if (thread == NULL || param == NULL)
{
return;
}
s = (NATIVE_STACK *)param;
seed_buf = NewBuf();
WriteBuf(seed_buf, s->MacAddress, 6);
GetExeName(exe_name, sizeof(exe_name));
WriteBufStr(seed_buf, exe_name);
state = StartAddIpTablesEntryForNativeStack(seed_buf->Buf, seed_buf->Size);
FreeBuf(seed_buf);
if (state == NULL)
{
NoticeThreadInit(thread);
return;
}
s->IpTablesInitOk = true;
NoticeThreadInit(thread);
while (true)
{
UINT wait_interval;
if (s->IpTablesHalt)
{
break;
}
if (MaintainAddIpTablesEntryForNativeStack(state))
{
counter = 0;
}
counter++;
wait_interval = NS_CHECK_IPTABLES_INTERVAL_INIT * counter;
wait_interval = MIN(wait_interval, NS_CHECK_IPTABLES_INTERVAL_MAX);
//Debug("NsIpTablesThread: wait for %u\n", wait_interval);
Wait(s->IpTablesHaltEvent, wait_interval);
}
EndAddIpTablesEntryForNativeStack(state);
}
// Stop the iptables tracking
void NsStopIpTablesTracking(NATIVE_STACK *a)
{
if (a->IpTablesThread == NULL)
{
return;
}
a->IpTablesHalt = true;
Set(a->IpTablesHaltEvent);
WaitThread(a->IpTablesThread, INFINITE);
ReleaseThread(a->IpTablesThread);
ReleaseEvent(a->IpTablesHaltEvent);
a->IpTablesThread = NULL;
a->IpTablesHaltEvent = NULL;
a->IpTablesInitOk = false;
a->IpTablesHalt = false;
}
// Release the stack
void FreeNativeStack(NATIVE_STACK *a)
{
@@ -288,6 +391,8 @@ void FreeNativeStack(NATIVE_STACK *a)
CloseEth(a->Eth);
FreeIPC(a->Ipc);
NsStopIpTablesTracking(a);
ReleaseCancel(a->Cancel);
ReleaseSock(a->Sock1);
@@ -312,12 +417,6 @@ NATIVE_STACK *NewNativeStack(CEDAR *cedar, char *device_name, char *mac_address_
return NULL;
}
if (cedar == NULL)
{
cedar = NewCedar(NULL, NULL);
release_cedar = true;
}
GetLocalHostIP4(&localhost);
// Open the Eth device
@@ -327,6 +426,12 @@ NATIVE_STACK *NewNativeStack(CEDAR *cedar, char *device_name, char *mac_address_
return NULL;
}
if (cedar == NULL)
{
cedar = NewCedar(NULL, NULL);
release_cedar = true;
}
a = ZeroMalloc(sizeof(NATIVE_STACK));
NewSocketPair(&a->Sock1, &a->Sock2, &localhost, 1, &localhost, 1);
@@ -353,6 +458,8 @@ NATIVE_STACK *NewNativeStack(CEDAR *cedar, char *device_name, char *mac_address_
ReleaseCedar(cedar);
}
a->IsIpRawMode = a->Eth->IsRawIpMode;
return a;
}
@@ -440,6 +547,457 @@ void NsGenMacAddress(void *dest, char *mac_address_seed, char *device_name)
Copy(dest, mac, 6);
}
// Add the iptables entries for native stack
IPTABLES_STATE *StartAddIpTablesEntryForNativeStack(void *seed, UINT seed_size)
{
IPTABLES_STATE *ret = NULL;
bool ok = false;
if (IsIpTablesSupported())
{
IPTABLES_ENTRY *e;
UINT i;
ret = ZeroMalloc(sizeof(IPTABLES_STATE));
ret->EntryList = NewListFast(NULL);
HashSha1(ret->SeedHash, seed, seed_size);
// Create a pair of entry
e = ZeroMalloc(sizeof(IPTABLES_ENTRY));
GenerateDummyIpAndMark(ret->SeedHash, e, 0);
StrCpy(e->Chain, sizeof(e->Chain), "OUTPUT");
Format(e->ConditionAndArgs, sizeof(e->ConditionAndArgs),
"-p tcp --tcp-flags RST RST --sport %u:%u ! -s %r/32 ! -d %r/32 -m connmark ! --mark 0x%x -j DROP",
NN_RAW_IP_PORT_START, NN_RAW_IP_PORT_END,
&e->DummySrcIp, &e->DummyDestIP, e->DummyMark);
Add(ret->EntryList, e);
e = ZeroMalloc(sizeof(IPTABLES_ENTRY));
GenerateDummyIpAndMark(ret->SeedHash, e, 1);
StrCpy(e->Chain, sizeof(e->Chain), "OUTPUT");
Format(e->ConditionAndArgs, sizeof(e->ConditionAndArgs),
"-p icmp --icmp-type 3/3 ! -s %r/32 ! -d %r/32 -m connmark ! --mark 0x%x -j DROP",
&e->DummySrcIp, &e->DummyDestIP, e->DummyMark);
Add(ret->EntryList, e);
ok = true;
// Insert entries if not exists
for (i = 0; i < LIST_NUM(ret->EntryList);i++)
{
UINT j;
IPTABLES_ENTRY *e = LIST_DATA(ret->EntryList, i);
for (j = 0;j < 100;j++)
{
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) != 0)
{
char cmdline[MAX_PATH];
Format(cmdline, sizeof(cmdline),
"iptables -D %s %s",
e->Chain, e->ConditionAndArgs);
system(cmdline);
}
else
{
break;
}
}
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0)
{
char cmdline[MAX_PATH];
Format(cmdline, sizeof(cmdline),
"iptables -I %s %s",
e->Chain, e->ConditionAndArgs);
system(cmdline);
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0)
{
Debug("Run \"%s\" failed.\n", cmdline);
ok = false;
break;
}
else
{
Debug("Run \"%s\" ok.\n", cmdline);
}
}
}
}
if (ok == false)
{
EndAddIpTablesEntryForNativeStack(ret);
ret = NULL;
}
return ret;
}
// Maintain the iptables
bool MaintainAddIpTablesEntryForNativeStack(IPTABLES_STATE *s)
{
UINT i;
bool ret = false;
if (s == NULL)
{
return false;
}
if (s->HasError)
{
return false;
}
// Insert entries if not exists
for (i = 0; i < LIST_NUM(s->EntryList);i++)
{
IPTABLES_ENTRY *e = LIST_DATA(s->EntryList, i);
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0)
{
char cmdline[MAX_PATH];
Format(cmdline, sizeof(cmdline),
"iptables -I %s %s",
e->Chain, e->ConditionAndArgs);
system(cmdline);
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0)
{
Debug("Run \"%s\" failed.\n", cmdline);
s->HasError = true;
break;
}
else
{
Debug("Run \"%s\" ok.\n", cmdline);
ret = true;
}
}
}
return ret;
}
// Stop the iptables management
void EndAddIpTablesEntryForNativeStack(IPTABLES_STATE *s)
{
UINT i;
if (s == NULL)
{
return;
}
// Delete entries
for (i = 0; i < LIST_NUM(s->EntryList);i++)
{
IPTABLES_ENTRY *e = LIST_DATA(s->EntryList, i);
UINT j;
for (j = 0;j < 100;j++)
{
if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) != 0)
{
char cmdline[MAX_PATH];
Format(cmdline, sizeof(cmdline),
"iptables -D %s %s",
e->Chain, e->ConditionAndArgs);
system(cmdline);
}
else
{
break;
}
}
}
FreeIpTablesState(s);
}
// Generate a set of dummy IP addresses and mark
void GenerateDummyIpAndMark(void *hash_seed, IPTABLES_ENTRY *e, UINT id)
{
PRAND *p;
BUF *b;
if (hash_seed == NULL || e == NULL)
{
return;
}
b = NewBuf();
WriteBufInt(b, id);
WriteBuf(b, hash_seed, SHA1_SIZE);
WriteBufStr(b, "20151002");
p = NewPRand(b->Buf, b->Size);
FreeBuf(b);
GenerateDummyIp(p, &e->DummySrcIp);
GenerateDummyIp(p, &e->DummyDestIP);
e->DummyMark = GenerateDummyMark(p);
FreePRand(p);
}
// Generate a dummy iptables mark
UINT GenerateDummyMark(PRAND *p)
{
UINT i;
if (p == NULL)
{
return 0;
}
while (true)
{
i = PRandInt(p);
if (i >= 1000000000 && i <= 0x7FFFFFFE)
{
return i;
}
}
return 0;
}
// Generate a dummy IP
void GenerateDummyIp(PRAND *p, IP *ip)
{
UINT i;
if (p == NULL || ip == NULL)
{
return;
}
Zero(ip, sizeof(IP));
for (i = 1;i < 4;i++)
{
UINT v = 0;
while (true)
{
v = PRandInt(p) % 256;
if (v >= 1 && v <= 254)
{
break;
}
}
ip->addr[i] = (UCHAR)v;
}
ip->addr[0] = 127;
}
// Search an entry
IPTABLES_ENTRY *SearchIpTables(IPTABLES_STATE *s, char *chain, IP *src_ip, IP *dest_ip, UINT mark)
{
char ip_str1[64];
char ip_str2[64];
char mark_str1[64];
char mark_str2[64];
UINT i;
if (s == NULL || chain == NULL || src_ip == NULL || dest_ip == NULL || mark == 0)
{
return NULL;
}
IPToStr(ip_str1, sizeof(ip_str1), src_ip);
IPToStr(ip_str2, sizeof(ip_str2), dest_ip);
ToStr(mark_str1, mark);
Format(mark_str2, sizeof(mark_str2), "%x", mark);
for (i = 0;i < LIST_NUM(s->EntryList);i++)
{
IPTABLES_ENTRY *e = LIST_DATA(s->EntryList, i);
if (StrCmpi(e->Chain, chain) == 0)
{
if (InStr(e->ConditionAndArgs, ip_str1) &&
InStr(e->ConditionAndArgs, ip_str2) &&
(InStr(e->ConditionAndArgs, mark_str1) || InStr(e->ConditionAndArgs, mark_str2)))
{
return e;
}
}
}
return NULL;
}
// Search an entry and get the line number
UINT GetCurrentIpTableLineNumber(char *chain, IP *src_ip, IP *dest_ip, UINT mark)
{
IPTABLES_STATE *s;
IPTABLES_ENTRY *e;
UINT ret = 0;
if (chain == NULL || src_ip == NULL || dest_ip == NULL || mark == 0)
{
return 0;
}
s = GetCurrentIpTables();
e = SearchIpTables(s, chain, src_ip, dest_ip, mark);
if (e != NULL)
{
ret = e->LineNumber;
}
FreeIpTablesState(s);
return ret;
}
// Free the iptables state
void FreeIpTablesState(IPTABLES_STATE *s)
{
UINT i;
if (s == NULL)
{
return;
}
for (i = 0;i < LIST_NUM(s->EntryList);i++)
{
IPTABLES_ENTRY *e = LIST_DATA(s->EntryList, i);
Free(e);
}
ReleaseList(s->EntryList);
Free(s);
}
// Get the current iptables state
IPTABLES_STATE *GetCurrentIpTables()
{
IPTABLES_STATE *ret = NULL;
TOKEN_LIST *t = NULL;
#ifdef OS_UNIX
t = UnixExec("iptables -L -x -n --line-numbers");
#endif // OS_UNIX
if (t != NULL)
{
UINT i;
UINT tmp_num = 0;
for (i = 0;i < t->NumTokens;i++)
{
char *line = t->Token[i];
if (StartWith(line, "Chain INPUT") ||
StartWith(line, "Chain FORWARD") ||
StartWith(line, "Chain OUTPUT"))
{
tmp_num++;
}
}
if (tmp_num >= 3)
{
char current_chain[64];
UINT mode = 0;
Zero(current_chain, sizeof(current_chain));
for (i = 0;i < t->NumTokens;i++)
{
char *line = t->Token[i];
if (StartWith(line, "Chain"))
{
TOKEN_LIST *t2 = ParseToken(line, " \t");
if (t2 != NULL)
{
if (t2->NumTokens >= 4)
{
StrCpy(current_chain, sizeof(current_chain), t2->Token[1]);
mode = 1;
if (ret == NULL)
{
ret = ZeroMalloc(sizeof(IPTABLES_STATE));
ret->EntryList = NewListFast(NULL);
}
}
FreeToken(t2);
}
}
if (mode == 1)
{
if (StartWith(line, "num"))
{
mode = 2;
}
}
else if (mode == 2)
{
TOKEN_LIST *t2 = ParseToken(line, " \t");
if (t2 != NULL)
{
if (t2->NumTokens >= 6 && ToInt(t2->Token[0]) != 0)
{
IPTABLES_ENTRY *e = ZeroMalloc(sizeof(IPTABLES_ENTRY));
StrCpy(e->Chain, sizeof(e->Chain), current_chain);
e->LineNumber = ToInt(t2->Token[0]);
StrCpy(e->ConditionAndArgs, sizeof(e->ConditionAndArgs), line);
Add(ret->EntryList, e);
}
FreeToken(t2);
}
}
}
}
FreeToken(t);
}
return ret;
}
// Get whether iptables is supported
bool IsIpTablesSupported()
{
#ifdef UNIX_LINUX
IPTABLES_STATE *s = GetCurrentIpTables();
if (s != NULL)
{
FreeIpTablesState(s);
return true;
}
else
{
return false;
}
#else // UNIX_LINUX
return false;
#endif // UNIX_LINUX
}
// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+46
View File
@@ -117,6 +117,10 @@
//// Constants
#define NS_MAC_ADDRESS_BYTE_1 0xDA // First byte of the MAC address
#define NS_CHECK_IPTABLES_INTERVAL_INIT (1 * 1000)
#define NS_CHECK_IPTABLES_INTERVAL_MAX (5 * 60 * 1000)
//// Type
struct NATIVE_STACK
{
@@ -132,6 +136,30 @@ struct NATIVE_STACK
SOCK *Sock2; // Sock2 (Used in the IPC side)
DHCP_OPTION_LIST CurrentDhcpOptionList; // Current DHCP options list
IP DnsServerIP; // IP address of the DNS server
IP DnsServerIP2; // IP address of the DNS server #2
bool IsIpRawMode;
IP MyIP_InCaseOfIpRawMode; // My IP
THREAD *IpTablesThread;
EVENT *IpTablesHaltEvent;
bool IpTablesHalt;
bool IpTablesInitOk;
};
struct IPTABLES_ENTRY
{
char Chain[64];
UINT LineNumber;
char ConditionAndArgs[MAX_SIZE];
IP DummySrcIp, DummyDestIP;
UINT DummyMark;
};
struct IPTABLES_STATE
{
UCHAR SeedHash[SHA1_SIZE];
LIST *EntryList;
bool HasError;
};
@@ -144,6 +172,24 @@ void NsMainThread(THREAD *thread, void *param);
void NsGenMacAddressSignatureForMachine(UCHAR *dst_last_2, UCHAR *src_mac_addr_4);
bool NsIsMacAddressOnLocalhost(UCHAR *mac);
bool NsStartIpTablesTracking(NATIVE_STACK *a);
void NsStopIpTablesTracking(NATIVE_STACK *a);
void NsIpTablesThread(THREAD *thread, void *param);
IPTABLES_STATE *GetCurrentIpTables();
void FreeIpTablesState(IPTABLES_STATE *s);
bool IsIpTablesSupported();
IPTABLES_ENTRY *SearchIpTables(IPTABLES_STATE *s, char *chain, IP *src_ip, IP *dest_ip, UINT mark);
UINT GetCurrentIpTableLineNumber(char *chain, IP *src_ip, IP *dest_ip, UINT mark);
IPTABLES_STATE *StartAddIpTablesEntryForNativeStack(void *seed, UINT seed_size);
void EndAddIpTablesEntryForNativeStack(IPTABLES_STATE *s);
bool MaintainAddIpTablesEntryForNativeStack(IPTABLES_STATE *s);
void GenerateDummyIpAndMark(void *hash_seed, IPTABLES_ENTRY *e, UINT id);
UINT GenerateDummyMark(PRAND *p);
void GenerateDummyIp(PRAND *p, IP *ip);
#endif // NATIVESTACK_H
+33 -2
View File
@@ -1324,6 +1324,7 @@ bool ServerAccept(CONNECTION *c)
char *error_detail = NULL;
char *error_detail_2 = NULL;
char ctoken_hash_str[64];
EAP_CLIENT *release_me_eap_client = NULL;
// Validate arguments
if (c == NULL)
@@ -1653,6 +1654,7 @@ bool ServerAccept(CONNECTION *c)
if (hub->Option != NULL)
{
radius_login_opt.In_CheckVLanId = hub->Option->AssignVLanIdByRadiusAttribute;
radius_login_opt.In_DenyNoVlanId = hub->Option->DenyAllRadiusLoginWithNoVlanAssign;
}
// Get the various flags
@@ -1674,6 +1676,14 @@ bool ServerAccept(CONNECTION *c)
if (c->IsInProc)
{
char tmp[MAX_SIZE];
UINT64 ptr;
ptr = PackGetInt64(p, "release_me_eap_client");
if (ptr != 0)
{
release_me_eap_client = (EAP_CLIENT *)ptr;
}
PackGetStr(p, "inproc_postfix", c->InProcPrefix, sizeof(c->InProcPrefix));
Zero(tmp, sizeof(tmp));
PackGetStr(p, "inproc_cryptname", tmp, sizeof(tmp));
@@ -2203,9 +2213,25 @@ bool ServerAccept(CONNECTION *c)
FreePack(p);
// Check the assigned VLAN ID
if (radius_login_opt.Out_VLanId != 0)
if (radius_login_opt.Out_IsRadiusLogin)
{
assigned_vlan_id = radius_login_opt.Out_VLanId;
if (radius_login_opt.In_CheckVLanId)
{
if (radius_login_opt.Out_VLanId != 0)
{
assigned_vlan_id = radius_login_opt.Out_VLanId;
}
if (radius_login_opt.In_DenyNoVlanId && assigned_vlan_id == 0 || assigned_vlan_id >= 4096)
{
// Deny this session
Unlock(hub->lock);
ReleaseHub(hub);
c->Err = ERR_ACCESS_DENIED;
error_detail = "In_DenyNoVlanId";
goto CLEANUP;
}
}
}
if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
@@ -3807,6 +3833,11 @@ CLEANUP:
SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
if (release_me_eap_client != NULL)
{
ReleaseEapClient(release_me_eap_client);
}
return ret;
}
+1621
View File
File diff suppressed because it is too large Load Diff
+246 -1
View File
@@ -117,15 +117,260 @@
#define RADIUS_DEFAULT_PORT 1812 // The default port number
#define RADIUS_RETRY_INTERVAL 500 // Retransmission interval
#define RADIUS_RETRY_TIMEOUT (10 * 1000) // Time-out period
#define RADIUS_INITIAL_EAP_TIMEOUT 1600 // Initial timeout for EAP
// RADIUS attributes
#define RADIUS_ATTRIBUTE_VLAN_ID 81
#define RADIUS_ATTRIBUTE_USER_NAME 1
#define RADIUS_ATTRIBUTE_NAS_IP 4
#define RADIUS_ATTRIBUTE_NAS_PORT 5
#define RADIUS_ATTRIBUTE_SERVICE_TYPE 6
#define RADIUS_ATTRIBUTE_FRAMED_PROTOCOL 7
#define RADIUS_ATTRIBUTE_FRAMED_MTU 12
#define RADIUS_ATTRIBUTE_STATE 24
#define RADIUS_ATTRIBUTE_VENDOR_SPECIFIC 26
#define RADIUS_ATTRIBUTE_CALLED_STATION_ID 30
#define RADIUS_ATTRIBUTE_CALLING_STATION_ID 31
#define RADIUS_ATTRIBUTE_NAS_ID 32
#define RADIUS_ATTRIBUTE_PROXY_STATE 33
#define RADIUS_ATTRIBUTE_ACCT_SESSION_ID 44
#define RADIUS_ATTRIBUTE_NAS_PORT_TYPE 61
#define RADIUS_ATTRIBUTE_TUNNEL_TYPE 64
#define RADIUS_ATTRIBUTE_TUNNEL_MEDIUM_TYPE 65
#define RADIUS_ATTRIBUTE_TUNNEL_CLIENT_ENDPOINT 66
#define RADIUS_ATTRIBUTE_TUNNEL_SERVER_ENDPOINT 67
#define RADIUS_ATTRIBUTE_EAP_MESSAGE 79
#define RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR 80
#define RADIUS_ATTRIBUTE_VLAN_ID 81
// RADIUS codes
#define RADIUS_CODE_ACCESS_REQUEST 1
#define RADIUS_CODE_ACCESS_ACCEPT 2
#define RADIUS_CODE_ACCESS_REJECT 3
#define RADIUS_CODE_ACCESS_CHALLENGE 11
// RADIUS vendor ID
#define RADIUS_VENDOR_MICROSOFT 311
// RADIUS MS attributes
#define RADIUS_MS_RAS_VENDOR 9
#define RADIUS_MS_CHAP_CHALLENGE 11
#define RADIUS_MS_VERSION 18
#define RADIUS_MS_CHAP2_RESPONSE 25
#define RADIUS_MS_RAS_CLIENT_NAME 34
#define RADIUS_MS_RAS_CLIENT_VERSION 35
#define RADIUS_MS_NETWORK_ACCESS_SERVER_TYPE 47
#define RADIUS_MS_RAS_CORRELATION 56
// EAP code
#define EAP_CODE_REQUEST 1
#define EAP_CODE_RESPONSE 2
#define EAP_CODE_SUCCESS 3
#define EAP_CODE_FAILURE 4
// EAP type
#define EAP_TYPE_IDENTITY 1
#define EAP_TYPE_LEGACY_NAK 3
#define EAP_TYPE_PEAP 25
#define EAP_TYPE_MS_AUTH 26
// MS-CHAPv2 opcodes
#define EAP_MSCHAPV2_OP_CHALLENGE 1
#define EAP_MSCHAPV2_OP_RESPONSE 2
#define EAP_MSCHAPV2_OP_SUCCESS 3
// EAP-TLS flags
#define EAP_TLS_FLAGS_LEN 0x80
#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40
#define EAP_TLS_FLAGS_START 0x20
////////// Modern implementation
#ifdef OS_WIN32
#pragma pack(push, 1)
#endif // OS_WIN32
struct EAP_MESSAGE
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Data[1500];
} GCC_PACKED;
struct EAP_MSCHAPV2_GENERAL
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Chap_Opcode;
} GCC_PACKED;
struct EAP_MSCHAPV2_CHALLENGE
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Chap_Opcode;
UCHAR Chap_Id;
USHORT Chap_Len;
UCHAR Chap_ValueSize; // = 16
UCHAR Chap_ChallengeValue[16];
char Chap_Name[256];
} GCC_PACKED;
struct EAP_MSCHAPV2_RESPONSE
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Chap_Opcode;
UCHAR Chap_Id;
USHORT Chap_Len;
UCHAR Chap_ValueSize; // = 49
UCHAR Chap_PeerChallange[16];
UCHAR Chap_Reserved[8];
UCHAR Chap_NtResponse[24];
UCHAR Chap_Flags;
char Chap_Name[256];
} GCC_PACKED;
struct EAP_MSCHAPV2_SUCCESS_SERVER
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Chap_Opcode;
UCHAR Chap_Id;
USHORT Chap_Len;
char Message[256];
} GCC_PACKED;
struct EAP_MSCHAPV2_SUCCESS_CLIENT
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR Chap_Opcode;
} GCC_PACKED;
struct EAP_PEAP
{
UCHAR Code;
UCHAR Id;
USHORT Len; // = sizeof(Data) + 5
UCHAR Type;
UCHAR TlsFlags;
} GCC_PACKED;
#ifdef OS_WIN32
#pragma pack(pop)
#endif // OS_WIN32
struct RADIUS_PACKET
{
UCHAR Code;
UCHAR PacketId;
LIST *AvpList;
UCHAR Authenticator[16];
UINT Parse_EapAuthMessagePos;
UINT Parse_AuthenticatorPos;
EAP_MESSAGE *Parse_EapMessage;
UINT Parse_EapMessage_DataSize;
UINT Parse_StateSize;
UCHAR Parse_State[256];
};
struct RADIUS_AVP
{
UCHAR Type;
UINT VendorId;
UCHAR VendorCode;
UCHAR Padding[3];
UCHAR DataSize;
UCHAR Data[256];
};
struct EAP_CLIENT
{
REF *Ref;
SOCK *UdpSock;
IP ServerIp;
UINT ServerPort;
char SharedSecret[MAX_SIZE];
char ClientIpStr[256];
char Username[MAX_USERNAME_LEN + 1];
UINT ResendTimeout;
UINT GiveupTimeout;
UCHAR TmpBuffer[4096];
UCHAR NextEapId;
UCHAR LastRecvEapId;
bool PeapMode;
UCHAR LastState[256];
UINT LastStateSize;
EAP_MSCHAPV2_CHALLENGE MsChapV2Challenge;
EAP_MSCHAPV2_SUCCESS_SERVER MsChapV2Success;
UCHAR ServerResponse[20];
SSL_PIPE *SslPipe;
UCHAR NextRadiusPacketId;
BUF *PEAP_CurrentReceivingMsg;
UINT PEAP_CurrentReceivingTotalSize;
UCHAR RecvLastCode;
UINT LastRecvVLanId;
};
void FreeRadiusPacket(RADIUS_PACKET *p);
BUF *GenerateRadiusPacket(RADIUS_PACKET *p, char *shared_secret);
RADIUS_PACKET *ParseRadiusPacket(void *data, UINT size);
RADIUS_PACKET *NewRadiusPacket(UCHAR code, UCHAR packet_id);
RADIUS_AVP *NewRadiusAvp(UCHAR type, UINT vendor_id, UCHAR vendor_code, void *data, UINT size);
RADIUS_AVP *GetRadiusAvp(RADIUS_PACKET *p, UCHAR type);
void RadiusTest();
EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, UINT resend_timeout, UINT giveup_timeout, char *client_ip_str, char *username);
void ReleaseEapClient(EAP_CLIENT *e);
void CleanupEapClient(EAP_CLIENT *e);
bool EapClientSendMsChapv2AuthRequest(EAP_CLIENT *e);
bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge);
void EapSetRadiusGeneralAttributes(RADIUS_PACKET *r, EAP_CLIENT *e);
bool EapSendPacket(EAP_CLIENT *e, RADIUS_PACKET *r);
RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r);
bool PeapClientSendMsChapv2AuthRequest(EAP_CLIENT *eap);
bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge);
bool StartPeapClient(EAP_CLIENT *e);
bool StartPeapSslClient(EAP_CLIENT *e);
bool SendPeapRawPacket(EAP_CLIENT *e, UCHAR *peap_data, UINT peap_size);
bool SendPeapPacket(EAP_CLIENT *e, void *msg, UINT msg_size);
bool GetRecvPeapMessage(EAP_CLIENT *e, EAP_MESSAGE *msg);
////////// Classical implementation
struct RADIUS_LOGIN_OPTION
{
bool In_CheckVLanId;
bool In_DenyNoVlanId;
UINT Out_VLanId;
bool Out_IsRadiusLogin;
};
// Function prototype
+8
View File
@@ -268,6 +268,14 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p
b = RadiusLogin(c, radius_server_addr, radius_server_port,
radius_secret, StrLen(radius_secret),
name, password, interval, mschap_v2_server_response_20, opt);
if (b)
{
if (opt != NULL)
{
opt->Out_IsRadiusLogin = true;
}
}
}
Lock(hub->lock);
+14
View File
@@ -4098,11 +4098,13 @@ void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
}
o->DisableKernelModeSecureNAT = CfgGetBool(f, "DisableKernelModeSecureNAT");
o->DisableIpRawModeSecureNAT = CfgGetBool(f, "DisableIpRawModeSecureNAT");
o->DisableUserModeSecureNAT = CfgGetBool(f, "DisableUserModeSecureNAT");
o->DisableCheckMacOnLocalBridge = CfgGetBool(f, "DisableCheckMacOnLocalBridge");
o->DisableCorrectIpOffloadChecksum = CfgGetBool(f, "DisableCorrectIpOffloadChecksum");
o->SuppressClientUpdateNotification = CfgGetBool(f, "SuppressClientUpdateNotification");
o->AssignVLanIdByRadiusAttribute = CfgGetBool(f, "AssignVLanIdByRadiusAttribute");
o->DenyAllRadiusLoginWithNoVlanAssign = CfgGetBool(f, "DenyAllRadiusLoginWithNoVlanAssign");
o->SecureNAT_RandomizeAssignIp = CfgGetBool(f, "SecureNAT_RandomizeAssignIp");
o->DetectDormantSessionInterval = CfgGetInt(f, "DetectDormantSessionInterval");
o->NoPhysicalIPOnPacketLog = CfgGetBool(f, "NoPhysicalIPOnPacketLog");
@@ -4182,6 +4184,7 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
CfgAddBool(f, "DropArpInPrivacyFilterMode", o->DropArpInPrivacyFilterMode);
CfgAddBool(f, "SuppressClientUpdateNotification", o->SuppressClientUpdateNotification);
CfgAddBool(f, "AssignVLanIdByRadiusAttribute", o->AssignVLanIdByRadiusAttribute);
CfgAddBool(f, "DenyAllRadiusLoginWithNoVlanAssign", o->DenyAllRadiusLoginWithNoVlanAssign);
CfgAddBool(f, "SecureNAT_RandomizeAssignIp", o->SecureNAT_RandomizeAssignIp);
CfgAddBool(f, "NoPhysicalIPOnPacketLog", o->NoPhysicalIPOnPacketLog);
CfgAddInt(f, "DetectDormantSessionInterval", o->DetectDormantSessionInterval);
@@ -4201,6 +4204,7 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
CfgAddInt(f, "SecureNAT_MaxIcmpSessionsPerIp", o->SecureNAT_MaxIcmpSessionsPerIp);
CfgAddInt(f, "AccessListIncludeFileCacheLifetime", o->AccessListIncludeFileCacheLifetime);
CfgAddBool(f, "DisableKernelModeSecureNAT", o->DisableKernelModeSecureNAT);
CfgAddBool(f, "DisableIpRawModeSecureNAT", o->DisableIpRawModeSecureNAT);
CfgAddBool(f, "DisableUserModeSecureNAT", o->DisableUserModeSecureNAT);
CfgAddBool(f, "DisableCheckMacOnLocalBridge", o->DisableCheckMacOnLocalBridge);
CfgAddBool(f, "DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum);
@@ -5005,6 +5009,9 @@ void SiWriteHubCfg(FOLDER *f, HUB *h)
CfgAddInt(f, "RadiusServerPort", h->RadiusServerPort);
CfgAddInt(f, "RadiusRetryInterval", h->RadiusRetryInterval);
CfgAddStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter);
CfgAddBool(f, "RadiusConvertAllMsChapv2AuthRequestToEap", h->RadiusConvertAllMsChapv2AuthRequestToEap);
CfgAddBool(f, "RadiusUsePeapInsteadOfEap", h->RadiusUsePeapInsteadOfEap);
}
Unlock(h->RadiusOptionLock);
@@ -5171,6 +5178,9 @@ void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
CfgGetStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter, sizeof(h->RadiusSuffixFilter));
h->RadiusConvertAllMsChapv2AuthRequestToEap = CfgGetBool(f, "RadiusConvertAllMsChapv2AuthRequestToEap");
h->RadiusUsePeapInsteadOfEap = CfgGetBool(f, "RadiusUsePeapInsteadOfEap");
if (interval == 0)
{
interval = RADIUS_RETRY_INTERVAL;
@@ -7486,6 +7496,7 @@ void SiCalledUpdateHub(SERVER *s, PACK *p)
o.DropArpInPrivacyFilterMode = PackGetBool(p, "DropArpInPrivacyFilterMode");
o.SuppressClientUpdateNotification = PackGetBool(p, "SuppressClientUpdateNotification");
o.AssignVLanIdByRadiusAttribute = PackGetBool(p, "AssignVLanIdByRadiusAttribute");
o.DenyAllRadiusLoginWithNoVlanAssign = PackGetBool(p, "DenyAllRadiusLoginWithNoVlanAssign");
o.SecureNAT_RandomizeAssignIp = PackGetBool(p, "SecureNAT_RandomizeAssignIp");
o.DetectDormantSessionInterval = PackGetInt(p, "DetectDormantSessionInterval");
o.VlanTypeId = PackGetInt(p, "VlanTypeId");
@@ -7527,6 +7538,7 @@ void SiCalledUpdateHub(SERVER *s, PACK *p)
o.AccessListIncludeFileCacheLifetime = ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME;
}
o.DisableKernelModeSecureNAT = PackGetBool(p, "DisableKernelModeSecureNAT");
o.DisableIpRawModeSecureNAT = PackGetBool(p, "DisableIpRawModeSecureNAT");
o.DisableUserModeSecureNAT = PackGetBool(p, "DisableUserModeSecureNAT");
o.DisableCheckMacOnLocalBridge = PackGetBool(p, "DisableCheckMacOnLocalBridge");
o.DisableCorrectIpOffloadChecksum = PackGetBool(p, "DisableCorrectIpOffloadChecksum");
@@ -9329,6 +9341,7 @@ void SiPackAddCreateHub(PACK *p, HUB *h)
PackAddBool(p, "DropArpInPrivacyFilterMode", h->Option->DropArpInPrivacyFilterMode);
PackAddBool(p, "SuppressClientUpdateNotification", h->Option->SuppressClientUpdateNotification);
PackAddBool(p, "AssignVLanIdByRadiusAttribute", h->Option->AssignVLanIdByRadiusAttribute);
PackAddBool(p, "DenyAllRadiusLoginWithNoVlanAssign", h->Option->DenyAllRadiusLoginWithNoVlanAssign);
PackAddInt(p, "ClientMinimumRequiredBuild", h->Option->ClientMinimumRequiredBuild);
PackAddBool(p, "SecureNAT_RandomizeAssignIp", h->Option->SecureNAT_RandomizeAssignIp);
PackAddBool(p, "NoPhysicalIPOnPacketLog", h->Option->NoPhysicalIPOnPacketLog);
@@ -9366,6 +9379,7 @@ void SiPackAddCreateHub(PACK *p, HUB *h)
PackAddInt(p, "SecureNAT_MaxIcmpSessionsPerIp", h->Option->SecureNAT_MaxIcmpSessionsPerIp);
PackAddInt(p, "AccessListIncludeFileCacheLifetime", h->Option->AccessListIncludeFileCacheLifetime);
PackAddBool(p, "DisableKernelModeSecureNAT", h->Option->DisableKernelModeSecureNAT);
PackAddBool(p, "DisableIpRawModeSecureNAT", h->Option->DisableIpRawModeSecureNAT);
PackAddBool(p, "DisableUserModeSecureNAT", h->Option->DisableUserModeSecureNAT);
PackAddBool(p, "DisableCheckMacOnLocalBridge", h->Option->DisableCheckMacOnLocalBridge);
PackAddBool(p, "DisableCorrectIpOffloadChecksum", h->Option->DisableCorrectIpOffloadChecksum);
+130 -16
View File
@@ -329,7 +329,7 @@ void NnDeleteSession(NATIVE_NAT *t, NATIVE_NAT_ENTRY *e)
break;
case NAT_ICMP:
Debug("NAT ICMP %u Deleted.", e->Id);
Debug("NAT ICMP %u Deleted.\n", e->Id);
break;
}
@@ -509,6 +509,7 @@ void NnCombineIp(NATIVE_NAT *t, IP_COMBINE *c, UINT offset, void *data, UINT siz
if (total_size == c->Size)
{
// Received whole of the IP packet
//Debug("Combine: %u\n", total_size);
NnIpReceived(t, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->Ttl,
c->HeadIpHeaderData, c->HeadIpHeaderDataSize, c->MaxL3Size);
@@ -1651,24 +1652,32 @@ UINT NnMapNewPublicPort(NATIVE_NAT *t, UINT protocol, UINT dest_ip, UINT dest_po
{
UINT i;
UINT base_port;
UINT port_start = 1025;
UINT port_end = 65500;
// Validate arguments
if (t == NULL)
{
return 0;
}
base_port = Rand32() % (65500 - 1025) + 1025;
if (t->IsRawIpMode)
{
port_start = NN_RAW_IP_PORT_START;
port_end = NN_RAW_IP_PORT_END;
}
for (i = 0;i < (65500 - 1025);i++)
base_port = Rand32() % (port_end - port_start) + port_start;
for (i = 0;i < (port_end - port_start);i++)
{
UINT port;
NATIVE_NAT_ENTRY tt;
NATIVE_NAT *e;
port = base_port + i;
if (port > 65500)
if (port > port_end)
{
port = port - 65500 + 1025;
port = port - port_end + port_start;
}
// Is this port vacant?
@@ -1688,6 +1697,10 @@ UINT NnMapNewPublicPort(NATIVE_NAT *t, UINT protocol, UINT dest_ip, UINT dest_po
// Examine whether the native NAT is available
bool NnIsActive(VH *v)
{
return NnIsActiveEx(v, NULL);
}
bool NnIsActiveEx(VH *v, bool *is_ipraw_mode)
{
// Validate arguments
if (v == NULL)
@@ -1705,6 +1718,14 @@ bool NnIsActive(VH *v)
return false;
}
if (v->NativeNat->Active)
{
if (is_ipraw_mode != NULL)
{
*is_ipraw_mode = v->NativeNat->IsRawIpMode;
}
}
return v->NativeNat->Active;
}
@@ -1745,7 +1766,7 @@ void NnMainLoop(NATIVE_NAT *t, NATIVE_STACK *a)
ipc = a->Ipc;
tubes[num_tubes++] = ipc->Sock->RecvTube;
tubes[num_tubes++] = ipc->Sock->SendTube;
//tubes[num_tubes++] = ipc->Sock->SendTube; // bug 2015.10.01 remove
tubes[num_tubes++] = t->HaltTube;
Zero(&yahoo_ip, sizeof(yahoo_ip));
@@ -1757,13 +1778,25 @@ void NnMainLoop(NATIVE_NAT *t, NATIVE_STACK *a)
next_dhcp_renew_tick = Tick64() + (UINT64)dhcp_renew_interval;
AddInterrupt(interrupt, next_dhcp_renew_tick);
while (t->Halt == false && t->v->UseNat && ((t->v->HubOption == NULL) || (t->v->HubOption->DisableKernelModeSecureNAT == false)))
while (t->Halt == false && t->v->UseNat)
{
UINT64 now = Tick64();
bool call_cancel = false;
bool state_changed = false;
UINT wait_interval;
if (t->v->HubOption != NULL)
{
if (t->IsRawIpMode == false && t->v->HubOption->DisableKernelModeSecureNAT)
{
break;
}
if (t->IsRawIpMode && t->v->HubOption->DisableIpRawModeSecureNAT)
{
break;
}
}
IPCFlushArpTable(ipc);
call_cancel = false;
@@ -1774,7 +1807,7 @@ LABEL_RESTART:
{
BUF *dns_query;
dns_src_port = NnGenSrcPort();
dns_src_port = NnGenSrcPort(a->IsIpRawMode);
dns_tran_id = Rand16();
// Start a connectivity check periodically
@@ -1877,7 +1910,7 @@ LABEL_RESTART:
// DNS response has been received
no_store = true;
tcp_src_port = NnGenSrcPort();
tcp_src_port = NnGenSrcPort(a->IsIpRawMode);
// Generate a TCP connection attempt packet
tcp_seq = Rand32();
@@ -2347,22 +2380,47 @@ LABEL_CLEANUP:
bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
{
BUF *dns_query;
BUF *dns_query2;
bool ok = false;
USHORT dns_tran_id = Rand16();
UINT64 next_send_tick = 0;
UINT64 giveup_time;
IPC *ipc;
UINT src_port = NnGenSrcPort();
UINT src_port = NnGenSrcPort(a->IsIpRawMode);
INTERRUPT_MANAGER *interrupt;
TUBE *tubes[3];
UINT num_tubes = 0;
IP yahoo_ip;
IP my_priv_ip;
UINT num_send_dns = 0;
IP using_dns;
// Validate arguments
if (a == NULL)
{
return false;
}
Copy(&using_dns, &a->DnsServerIP, sizeof(IP));
// Get my physical IP
if (a->IsIpRawMode)
{
if (GetMyPrivateIP(&my_priv_ip, false) == false)
{
Debug("NnTestConnectivity: GetMyPrivateIP failed.\n");
return false;
}
else
{
Debug("NnTestConnectivity: GetMyPrivateIP ok: %r\n", &my_priv_ip);
if (a->Eth != NULL)
{
Copy(&a->Eth->MyPhysicalIPForce, &my_priv_ip, sizeof(IP));
}
}
}
ipc = a->Ipc;
interrupt = NewInterruptManager();
@@ -2381,6 +2439,10 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
IPToUINT(&ipc->ClientIPAddress), src_port, IPToUINT(&a->DnsServerIP), 53),
IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP), IP_PROTO_UDP, 0);
dns_query2 = NnBuildIpPacket(NnBuildUdpPacket(NnBuildDnsQueryPacket(NN_CHECK_HOSTNAME, dns_tran_id),
IPToUINT(&ipc->ClientIPAddress), src_port, IPToUINT(&a->DnsServerIP), 53),
IPToUINT(&ipc->ClientIPAddress), IPToUINT(&a->DnsServerIP2), IP_PROTO_UDP, 0);
giveup_time = Tick64() + NN_CHECK_CONNECTIVITY_TIMEOUT;
AddInterrupt(interrupt, giveup_time);
while (true)
@@ -2401,7 +2463,16 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
AddInterrupt(interrupt, next_send_tick);
IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
if ((num_send_dns % 2) == 0)
{
IPCSendIPv4(ipc, dns_query->Buf, dns_query->Size);
}
else
{
IPCSendIPv4(ipc, dns_query2->Buf, dns_query2->Size);
}
num_send_dns++;
}
// Happy processing
@@ -2424,7 +2495,8 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
if (pkt != NULL)
{
if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP &&
pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) &&
(pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP) ||
pkt->L3.IPv4Header->SrcIP == IPToUINT(&a->DnsServerIP2)) &&
pkt->L3.IPv4Header->DstIP == IPToUINT(&ipc->ClientIPAddress) &&
pkt->L4.UDPHeader->SrcPort == Endian16(53) && pkt->L4.UDPHeader->DstPort == Endian16(src_port))
{
@@ -2437,6 +2509,9 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
if (NnParseDnsResponsePacket(pkt->Payload, pkt->PayloadSize, &ret_ip))
{
UINTToIP(&using_dns, pkt->L3.IPv4Header->SrcIP);
Debug("NativeStack: Using DNS: %r\n", &using_dns);
Copy(&yahoo_ip, &ret_ip, sizeof(IP));
}
}
@@ -2466,6 +2541,7 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
}
FreeBuf(dns_query);
FreeBuf(dns_query2);
if (IsZeroIP(&yahoo_ip) == false)
{
@@ -2589,13 +2665,37 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
FreeInterruptManager(interrupt);
if (ok)
{
if (IsZeroIP(&using_dns) == false)
{
Copy(&a->DnsServerIP, &using_dns, sizeof(IP));
}
if (a->IsIpRawMode)
{
if (NsStartIpTablesTracking(a) == false)
{
Debug("NsStartIpTablesTracking failed.\n");
ok = false;
}
}
}
return ok;
}
// Generate source port number by a random number
UINT NnGenSrcPort()
UINT NnGenSrcPort(bool raw_ip_mode)
{
return 1025 + Rand32() % (65500 - 1025);
if (raw_ip_mode == false)
{
return 1025 + Rand32() % (65500 - 1025);
}
else
{
return NN_RAW_IP_PORT_START + Rand32() % (NN_RAW_IP_PORT_END - NN_RAW_IP_PORT_START);
}
}
// Get a next good interface for the native NAT
@@ -2617,7 +2717,9 @@ NATIVE_STACK *NnGetNextInterface(NATIVE_NAT *t)
t->NextWaitTimeForRetry = NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM * MIN((t->FailedCount + 1), NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT);
// Get the device list
device_list = GetEthList();
device_list = GetEthListEx(NULL,
!(t->v->HubOption != NULL && t->v->HubOption->DisableKernelModeSecureNAT),
!(t->v->HubOption != NULL && t->v->HubOption->DisableIpRawModeSecureNAT));
if (device_list == NULL || device_list->NumTokens == 0)
{
@@ -2720,11 +2822,17 @@ NATIVE_STACK *NnGetNextInterface(NATIVE_NAT *t)
// Determine the DNS server to use
UINTToIP(&ret->DnsServerIP, opt.DnsServer);
UINTToIP(&ret->DnsServerIP2, opt.DnsServer2);
if (IsZeroIP(&ret->DnsServerIP))
{
// Use 8.8.8.8 instead If the DNS is not assigned from the DHCP server
SetIP(&ret->DnsServerIP, 8, 8, 8, 8);
}
if (IsZeroIP(&ret->DnsServerIP2))
{
// Use 8.8.4.4 instead If the DNS is not assigned from the DHCP server
SetIP(&ret->DnsServerIP2, 8, 8, 4, 4);
}
// Connectivity test
// (always fail if the default gateway is not set)
@@ -2773,7 +2881,7 @@ void NativeNatThread(THREAD *thread, void *param)
{
NATIVE_STACK *a;
while (t->v->UseNat == false || (t->v->HubOption != NULL && t->v->HubOption->DisableKernelModeSecureNAT))
while (t->v->UseNat == false || t->v->HubOption == NULL || (t->v->HubOption->DisableKernelModeSecureNAT && t->v->HubOption->DisableIpRawModeSecureNAT))
{
if (t->Halt)
{
@@ -2802,6 +2910,8 @@ void NativeNatThread(THREAD *thread, void *param)
// Acquisition success
Debug("NnGetNextInterface Ok: %s\n", a->DeviceName);
t->IsRawIpMode = a->IsIpRawMode;
Lock(t->Lock);
{
if (a->Sock1 != NULL)
@@ -2830,6 +2940,8 @@ void NativeNatThread(THREAD *thread, void *param)
NnMainLoop(t, a);
Debug("NnMainLoop End.\n");
t->IsRawIpMode = false;
t->Active = false;
t->PublicIP = 0;
@@ -7425,6 +7537,8 @@ void VirtualIcmpEchoRequestReceived(VH *v, UINT src_ip, UINT dst_ip, void *data,
return;
}
//Debug("ICMP: %u\n", size);
if (NnIsActive(v))
{
// Process by the Native NAT
+8 -3
View File
@@ -115,10 +115,13 @@
#define VIRTUAL_H
#define NN_RAW_IP_PORT_START 61001
#define NN_RAW_IP_PORT_END 65535
#define VIRTUAL_TCP_SEND_TIMEOUT (21 * 1000)
#define NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM (60 * 1000)
#define NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT 15
#define NN_NEXT_WAIT_TIME_FOR_DEVICE_ENUM (30 * 1000)
#define NN_NEXT_WAIT_TIME_MAX_FAIL_COUNT 30
#define NN_HOSTNAME_FORMAT "securenat-%s"
#define NN_HOSTNAME_STARTWITH "securenat-"
@@ -191,6 +194,7 @@ struct NATIVE_NAT
LIST *IpCombine; // IP combining list
UINT CurrentIpQuota; // Current IP combining quota
UCHAR CurrentMacAddress[6]; // Current MAC address
bool IsRawIpMode; // Is RAW_IP mode
};
// ARP entry
@@ -643,7 +647,7 @@ BUF *NnBuildDnsQueryPacket(char *hostname, USHORT tran_id);
BUF *NnBuildUdpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port);
BUF *NnBuildTcpPacket(BUF *payload, UINT src_ip, USHORT src_port, UINT dst_ip, USHORT dst_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss);
BUF *NnBuildIpPacket(BUF *payload, UINT src_ip, UINT dst_ip, UCHAR protocol, UCHAR ttl);
UINT NnGenSrcPort();
UINT NnGenSrcPort(bool raw_ip_mode);
bool NnParseDnsResponsePacket(UCHAR *data, UINT size, IP *ret_ip);
BUF *NnReadDnsRecord(BUF *buf, bool answer, USHORT *ret_type, USHORT *ret_class);
bool NnReadDnsLabel(BUF *buf);
@@ -656,6 +660,7 @@ UINT GetHashNativeNatTableForRecv(void *p);
void NnSetNat(NATIVE_NAT_ENTRY *e, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT pub_ip, UINT pub_port);
bool NnIsActive(VH *v);
bool NnIsActiveEx(VH *v, bool *is_ipraw_mode);
void NnUdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, UINT max_l3_size);
void NnTcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *old_tcp, void *data, UINT size, UINT max_l3_size);
void NnIcmpEchoRecvForInternet(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, UCHAR ttl, void *icmp_data, UINT icmp_size, UCHAR *ip_header, UINT ip_header_size, UINT max_l3_size);