1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-12-26 01:59:53 +03:00

Merge branch 'master' into rpmspec_update

* master:
  v4.19-9582-beta
This commit is contained in:
Jeff Tang 2015-10-07 11:45:14 -04:00
commit 5f0f05aa76
59 changed files with 4281 additions and 109 deletions

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.

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

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

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

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

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

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

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

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;
// ==============================================================

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

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

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

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

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;

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

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

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

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

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

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

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

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

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 *

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.

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

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

File diff suppressed because it is too large Load Diff

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

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

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

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

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

View File

@ -1,4 +1,4 @@
BUILD_NUMBER 9578
BUILD_NUMBER 9582
VERSION 419
BUILD_NAME beta
BUILD_DATE 20150915_143935
BUILD_DATE 20151006_145630

View File

@ -423,6 +423,7 @@ typedef struct STRMAP_ENTRY STRMAP_ENTRY;
typedef struct SHARED_BUFFER SHARED_BUFFER;
typedef struct HASH_LIST HASH_LIST;
typedef struct HASH_ENTRY HASH_ENTRY;
typedef struct PRAND PRAND;
// Str.h
typedef struct TOKEN_LIST TOKEN_LIST;

View File

@ -134,6 +134,70 @@
static UINT fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
// New PRand
PRAND *NewPRand(void *key, UINT key_size)
{
PRAND *r;
UCHAR dummy[256];
if (key == NULL || key_size == 0)
{
key = "DUMMY";
key_size = 5;
}
r = ZeroMalloc(sizeof(PRAND));
HashSha1(r->Key, key, key_size);
r->Rc4 = NewCrypt(key, key_size);
Zero(dummy, sizeof(dummy));
Encrypt(r->Rc4, dummy, dummy, 256);
return r;
}
// Free PRand
void FreePRand(PRAND *r)
{
if (r == NULL)
{
return;
}
FreeCrypt(r->Rc4);
Free(r);
}
// Generate PRand
void PRand(PRAND *p, void *data, UINT size)
{
if (p == NULL)
{
return;
}
Zero(data, size);
Encrypt(p->Rc4, data, data, size);
}
// Generate UINT PRand
UINT PRandInt(PRAND *p)
{
UINT r;
if (p == NULL)
{
return 0;
}
PRand(p, &r, sizeof(UINT));
return r;
}
// Check whether the specified key item is in the hash list
bool IsInHashListKey(HASH_LIST *h, UINT key)
{
@ -2368,6 +2432,28 @@ UINT PeekFifo(FIFO *f, void *p, UINT size)
return read_size;
}
// Read all data from FIFO
BUF *ReadFifoAll(FIFO *f)
{
BUF *buf;
UCHAR *tmp;
UINT size;
if (f == NULL)
{
return NewBuf();
}
size = FifoSize(f);
tmp = Malloc(size);
ReadFifo(f, tmp, size);
buf = MemToBuf(tmp, size);
Free(tmp);
return buf;
}
// Read from the FIFO
UINT ReadFifo(FIFO *f, void *p, UINT size)
{
@ -3128,6 +3214,21 @@ bool WriteBufInt(BUF *b, UINT value)
return true;
}
// Write a short integer in the the buffer
bool WriteBufShort(BUF *b, USHORT value)
{
// Validate arguments
if (b == NULL)
{
return false;
}
value = Endian16(value);
WriteBuf(b, &value, sizeof(USHORT));
return true;
}
// Write a UCHAR to the buffer
bool WriteBufChar(BUF *b, UCHAR uc)
{
@ -3194,6 +3295,23 @@ UINT ReadBufInt(BUF *b)
return Endian32(value);
}
// Read a short integer from the buffer
USHORT ReadBufShort(BUF *b)
{
USHORT value;
// Validate arguments
if (b == NULL)
{
return 0;
}
if (ReadBuf(b, &value, sizeof(USHORT)) != sizeof(USHORT))
{
return 0;
}
return Endian16(value);
}
// Write the buffer to a buffer
void WriteBufBuf(BUF *b, BUF *bb)
{
@ -3459,6 +3577,23 @@ BUF *ReadRemainBuf(BUF *b)
return ReadBufFromBuf(b, size);
}
// Get the length of the rest
UINT ReadBufRemainSize(BUF *b)
{
// Validate arguments
if (b == NULL)
{
return 0;
}
if (b->Size < b->Current)
{
return 0;
}
return b->Size - b->Current;
}
// Clone the buffer
BUF *CloneBuf(BUF *b)
{

View File

@ -236,6 +236,13 @@ struct HASH_LIST
LIST *AllList;
};
// PRAND
struct PRAND
{
UCHAR Key[20];
CRYPT *Rc4;
};
// Function prototype
HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list);
void ReleaseHashList(HASH_LIST *h);
@ -250,6 +257,11 @@ void UnlockHashList(HASH_LIST *h);
bool IsInHashListKey(HASH_LIST *h, UINT key);
void *HashListKeyToPointer(HASH_LIST *h, UINT key);
PRAND *NewPRand(void *key, UINT key_size);
void FreePRand(PRAND *r);
void PRand(PRAND *p, void *data, UINT size);
UINT PRandInt(PRAND *p);
LIST *NewCandidateList();
void FreeCandidateList(LIST *o);
int ComapreCandidate(void *p1, void *p2);
@ -310,11 +322,13 @@ void FreeBuf(BUF *b);
bool BufToFile(IO *o, BUF *b);
BUF *FileToBuf(IO *o);
UINT ReadBufInt(BUF *b);
USHORT ReadBufShort(BUF *b);
UINT64 ReadBufInt64(BUF *b);
UCHAR ReadBufChar(BUF *b);
bool WriteBufInt(BUF *b, UINT value);
bool WriteBufInt64(BUF *b, UINT64 value);
bool WriteBufChar(BUF *b, UCHAR uc);
bool WriteBufShort(BUF *b, USHORT value);
bool ReadBufStr(BUF *b, char *str, UINT size);
bool WriteBufStr(BUF *b, char *str);
void WriteBufLine(BUF *b, char *str);
@ -332,10 +346,12 @@ BUF *CloneBuf(BUF *b);
BUF *MemToBuf(void *data, UINT size);
BUF *RandBuf(UINT size);
BUF *ReadRemainBuf(BUF *b);
UINT ReadBufRemainSize(BUF *b);
bool CompareBuf(BUF *b1, BUF *b2);
UINT PeekFifo(FIFO *f, void *p, UINT size);
UINT ReadFifo(FIFO *f, void *p, UINT size);
BUF *ReadFifoAll(FIFO *f);
void ShrinkFifoMemory(FIFO *f);
UCHAR *GetFifoPointer(FIFO *f);
UCHAR *FifoPtr(FIFO *f);

View File

@ -5842,6 +5842,11 @@ SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE);
}
if (server_mode == false)
{
SSL_CTX_set_options(ssl_ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
}
ssl = SSL_new(ssl_ctx);
}
Unlock(openssl_lock);
@ -8907,10 +8912,36 @@ void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
if (c1 != NULL)
{
reads[num_read++] = p1 = c1->pipe_read;
if (c1->SpecialFlag)
{
if (c1->pipe_special_read2 != -1 && c1->pipe_special_read2 != 0)
{
reads[num_read++] = c1->pipe_special_read2;
}
if (c1->pipe_special_read3 != -1 && c1->pipe_special_read3 != 0)
{
reads[num_read++] = c1->pipe_special_read3;
}
}
}
if (c2 != NULL)
{
reads[num_read++] = p2 = c2->pipe_read;
if (c2->SpecialFlag)
{
if (c2->pipe_special_read2 != -1 && c2->pipe_special_read2 != 0)
{
reads[num_read++] = c2->pipe_special_read2;
}
if (c2->pipe_special_read3 != -1 && c2->pipe_special_read3 != 0)
{
reads[num_read++] = c2->pipe_special_read3;
}
}
}
// Call the select
@ -8991,6 +9022,8 @@ CANCEL *UnixNewCancel()
UnixNewPipe(&c->pipe_read, &c->pipe_write);
c->pipe_special_read2 = c->pipe_special_read3 = -1;
return c;
}
@ -12307,6 +12340,36 @@ SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR ra
return NewUDPEx2Rand(ipv6, ip, hash, sizeof(hash), num_retry);
}
// Set the DF bit of the socket
void ClearSockDfBit(SOCK *s)
{
#ifdef IP_PMTUDISC_DONT
#ifdef IP_MTU_DISCOVER
UINT value = IP_PMTUDISC_DONT;
if (s == NULL)
{
return;
}
setsockopt(s->socket, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&value, sizeof(value));
#endif // IP_MTU_DISCOVER
#endif // IP_PMTUDISC_DONT
}
// Set the header-include option
void SetRawSockHeaderIncludeOption(SOCK *s, bool enable)
{
UINT value = BOOL_TO_INT(enable);
if (s == NULL || s->IsRawSocket == false)
{
return;
}
setsockopt(s->socket, IPPROTO_IP, IP_HDRINCL, (char *)&value, sizeof(value));
s->RawIP_HeaderIncludeFlag = enable;
}
// Create and initialize the UDP socket
// If port is specified as 0, system assigns a certain port.
SOCK *NewUDP(UINT port)

View File

@ -313,6 +313,7 @@ struct SOCK
UINT Reverse_MyServerPort; // Self port number when using the reverse socket
UCHAR Ssl_Init_Async_SendAlert[2]; // Initial state of SSL send_alert
bool AcceptOnlyTls; // Accept only TLS (disable SSLv3)
bool RawIP_HeaderIncludeFlag;
#ifdef ENABLE_SSL_LOGGING
// SSL Logging (for debug)
@ -371,6 +372,7 @@ struct CANCEL
void *hEvent; // Pointer to a Win32 event handle
#else // OS_WIN32
int pipe_read, pipe_write; // Pipe
int pipe_special_read2, pipe_special_read3;
#endif // OS_WIN32
};
@ -1323,6 +1325,8 @@ SOCK *NewUDP4(UINT port, IP *ip);
SOCK *NewUDP6(UINT port, IP *ip);
SOCK *NewUDPEx2Rand(bool ipv6, IP *ip, void *rand_seed, UINT rand_seed_size, UINT num_retry);
SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR rand_port_id);
void ClearSockDfBit(SOCK *s);
void SetRawSockHeaderIncludeOption(SOCK *s, bool enable);
UINT GetNewAvailableUdpPortRand();
UINT NewRandPortByMachineAndExePath(UINT start_port, UINT end_port, UINT additional_int);
void DisableUDPChecksum(SOCK *s);

View File

@ -2874,6 +2874,7 @@ bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size)
{
// Quit analysing since this is fragmented
p->TypeL4 = L4_FRAGMENT;
return true;
}

View File

@ -158,13 +158,14 @@ UINT64 Tick64ToTime64(UINT64 tick)
}
LockList(tk64->AdjustTime);
{
UINT i;
for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++)
INT i;
for (i = ((INT)LIST_NUM(tk64->AdjustTime) - 1); i >= 0; i--)
{
ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i);
if (t->Tick <= tick)
{
ret = t->Time + (tick - t->Tick);
break;
}
}
}

View File

@ -115,7 +115,7 @@
#define TICK64_H
// Maximum number of correction list entries
#define MAX_ADJUST_TIME 5000
#define MAX_ADJUST_TIME 1024
// Correction list entry
struct ADJUST_TIME

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -559,6 +559,7 @@ HUB_AO_DropArpInPrivacyFilterMode Drop ARP packets if the both source and dest
HUB_AO_SuppressClientUpdateNotification Suppress the update notification screen on the VPN Client.
HUB_AO_FloodingSendQueueBufferQuota Specify the quota limitation value (in bytes) of the sending queue buffer size which the flooding operation on the Virtual Hub can consume. The quota value is applied on the total length of sending queues of all active VPN sessions. Specify '0' to disable the quota. This option is effective to solve the out-of-memory problem on the network where there are many flooding packets.
HUB_AO_AssignVLanIdByRadiusAttribute Enable the VLAN ID dynamic assignment function. Each VPN session will be assigned its own VLAN ID by the RADIUS attribute value when the user is authenticated by the external RADIUS server unless the user object has a VLAN ID security policy. The RADIUS attribute with the name "Tunnel-Pvt-Group-ID" (ID = 81) will be used as the VLAN ID. The data type must be STRING.
HUB_AO_DenyAllRadiusLoginWithNoVlanAssign If you set this option to non-zero value, then all users, which RADIUS server returns no "Tunnel-Pvt-Group-ID" (ID = 81) value, will be denied to connect to the Virtual Hub. (Only if the values of AssignVLanIdByRadiusAttribute is non-zero value.)
HUB_AO_SecureNAT_RandomizeAssignIp If you set this option to non-zero value, then the Virtual DHCP Server of the SecureNAT function will choose an unused IP address randomly from the DHCP pool while the default behavior is to choose the first unused IP address.
HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value, then the Virtual Hub will treat the VPN sessions, which have transmitted no packets for the last specified intervals (in seconds), as Dormant Sessions. The Virtual Hub will not flood packets, which should be flood, to any Dormant Sessions.
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
@ -1498,6 +1499,7 @@ SM_SNAT_STATUS SecureNAT 运行状态
SM_SNAT_NUM_SESSION %u 个会话
SM_SNAT_NUM_CLIENT %u 个客户端
SM_SNAT_IS_KERNEL 内核模式 NAT 功能是活跃的
SM_SNAT_IS_RAW Raw IP mode NAT 功能是活跃的
SM_BRIDGE_TOO_OLD_VER 当前连接的 VPN Server 版本不支持本地网桥功能。\r\n请更新到最新版本。
SM_BRIDGE_UNSUPPORTED 当前连接的 VPN Server 运行的操作系统无法使用本地网桥功能。请参阅 VPN Server 在线文档以获得支持本地网桥功能的操作系统列表。
SM_BRIDGE_WPCAP_REMOTE 为在此 VPN Server 上使用本地网桥功能,您必须安装 WinPcap 软件。WinPcap 软件当前没有在服务器上安装。\r\n\r\n要进行 WinPcap 软件的安装,您必须在运行 VPN Server 的服务器上启动 SoftEther VPN Server 管理器,然后连接到本机 (您自己计算机的位置),打开本地网桥功能设置窗口。\r\n首先退出此管理会话然后在此服务器上启动 SoftEther VPN Server 管理器之后,连接到本机并继续设置进程。

View File

@ -553,6 +553,7 @@ HUB_AO_DropArpInPrivacyFilterMode Drop ARP packets if the both source and dest
HUB_AO_SuppressClientUpdateNotification Suppress the update notification screen on the VPN Client.
HUB_AO_FloodingSendQueueBufferQuota Specify the quota limitation value (in bytes) of the sending queue buffer size which the flooding operation on the Virtual Hub can consume. The quota value is applied on the total length of sending queues of all active VPN sessions. Specify '0' to disable the quota. This option is effective to solve the out-of-memory problem on the network where there are many flooding packets.
HUB_AO_AssignVLanIdByRadiusAttribute Enable the VLAN ID dynamic assignment function. Each VPN session will be assigned its own VLAN ID by the RADIUS attribute value when the user is authenticated by the external RADIUS server unless the user object has a VLAN ID security policy. The RADIUS attribute with the name "Tunnel-Pvt-Group-ID" (ID = 81) will be used as the VLAN ID. The data type must be STRING.
HUB_AO_DenyAllRadiusLoginWithNoVlanAssign If you set this option to non-zero value, then all users, which RADIUS server returns no "Tunnel-Pvt-Group-ID" (ID = 81) value, will be denied to connect to the Virtual Hub. (Only if the values of AssignVLanIdByRadiusAttribute is non-zero value.)
HUB_AO_SecureNAT_RandomizeAssignIp If you set this option to non-zero value, then the Virtual DHCP Server of the SecureNAT function will choose an unused IP address randomly from the DHCP pool while the default behavior is to choose the first unused IP address.
HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value, then the Virtual Hub will treat the VPN sessions, which have transmitted no packets for the last specified intervals (in seconds), as Dormant Sessions. The Virtual Hub will not flood packets, which should be flood, to any Dormant Sessions.
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
@ -1488,6 +1489,7 @@ SM_SNAT_STATUS SecureNAT Operating Status
SM_SNAT_NUM_SESSION %u Session
SM_SNAT_NUM_CLIENT %u Client
SM_SNAT_IS_KERNEL Kernel-mode NAT is Active
SM_SNAT_IS_RAW Raw IP mode NAT is Active
SM_BRIDGE_TOO_OLD_VER The Local Bridge function is not supported by the version of the VPN Server that is currently connected. \r\nTry update to a new version.
SM_BRIDGE_UNSUPPORTED Unable to use the Local Bridge function with the operating system that this VPN Server is operating on. For the list of operating system that the Local Bridge function can be used on, refer to the online documentation of the VPN Server.
SM_BRIDGE_WPCAP_REMOTE In order to use the Local Bridge function on this VPN Server, you must install the WinPcap software. The software WinPcap is currently not installed on the server computer. \r\n\r\nTo continue the installation of the WinPcap software, you must start SoftEther VPN Server Manager on the server computer that is running VPN Server and then while connected to localhost (location of your own computer), have the Local Bridge Function Setting window displayed. \r\nTo continue, first exit this management session, and then, after starting SoftEther VPN Server Manager on the server computer, connect to localhost and continue the setting process.

View File

@ -574,6 +574,7 @@ HUB_AO_DropArpInPrivacyFilterMode 送信元および宛先の両方のセッ
HUB_AO_SuppressClientUpdateNotification VPN Client のアップデート通知画面の表示を抑制します。
HUB_AO_FloodingSendQueueBufferQuota パケットの仮想 HUB 内におけるフラッディング動作時において消費することを許容する送信キューのバッファサイズの制限値 (バイト数) を指定します。クオータは、すべての接続中の VPN セッションの送信キューの合計長さに対してグローバルに適用されます。0 を指定すると無制限になります。このオプションは、フラッディングパケットが多発するネットワークにおいてメモリ消費量が増大する問題を解決するために利用できます。
HUB_AO_AssignVLanIdByRadiusAttribute VLAN ID の動的割り当て機能を有効にします。VPN 接続するユーザーオブジェクトのセキュリティポリシーに VLAN ID が指定されていない場合は、各 VPN セッションはユーザー認証を行った RADIUS サーバーから返却される RADIUS 属性の値に基づき VLAN が割当てられます。RADIUS 属性のうち、 "Tunnel-Pvt-Group-ID" (ID = 81) の値が使用されます。データ型は文字列である必要があります。
HUB_AO_DenyAllRadiusLoginWithNoVlanAssign この項目が 1 (有効) の場合は、RADIUS サーバーが "Tunnel-Pvt-Group-ID" (ID = 81) の値を返却しなかった場合は VPN 接続が拒否されます。(AssignVLanIdByRadiusAttribute の値が 1 の場合に限ります。)
HUB_AO_SecureNAT_RandomizeAssignIp この項目が 1 (有効) の場合は、SecureNAT 機能における仮想 DHCP サーバーは、DHCP クライアントに対して割当てる IP アドレスを指定された IP アドレスプール内の未使用アドレスからランダムに選択するようになります。なお、既定の動作は、未使用アドレスのうち最初のアドレスを割当てるようになっています。
HUB_AO_DetectDormantSessionInterval この項目が 0 以外の場合は、指定された秒数無通信であった VPN セッションをドーマント状態 (休止状態) として識別します。ドーマント状態の VPN セッションに対しては、仮想 HUB 内でフラッディングされるべきパケットがフラッディングされなくなります。
HUB_AO_NoPhysicalIPOnPacketLog この項目が 0 (有効) の場合は、パケットログに送信元および宛先 VPN セッションの物理的な接続元 VPN クライアントの IP アドレスが記録されないようになります。
@ -1492,6 +1493,7 @@ SM_SNAT_STATUS SecureNAT の動作状況
SM_SNAT_NUM_SESSION %u セッション
SM_SNAT_NUM_CLIENT %u クライアント
SM_SNAT_IS_KERNEL カーネルモード NAT で動作中
SM_SNAT_IS_RAW Raw IP モード NAT で動作中
SM_BRIDGE_TOO_OLD_VER 現在接続している VPN Server のバージョンでは、ローカルブリッジ機能はサポートされていません。\r\n新しいバージョンにアップデートしてみてください。
SM_BRIDGE_UNSUPPORTED この VPN Server が動作しているオペレーティングシステム上では、ローカルブリッジ機能を使用することはできません。ローカルブリッジ機能が使用できるオペレーティングシステムの一覧については、VPN Server のオンラインドキュメントを参照してください。
SM_BRIDGE_WPCAP_REMOTE この VPN Server 上でローカルブリッジ機能を使用するためには、WinPcap ソフトウェアをインストールする必要があります。現在、サーバー コンピュータ上には WinPcap ソフトウェアがインストールされていません。\r\n\r\nWinPcap ソフトウェアのインストールを続行するためには、VPN Server が動作しているサーバー コンピュータ上で SoftEther VPN サーバー管理マネージャを起動し、localhost (自分自身) に対して接続した状態で、ローカルブリッジ機能設定画面を表示する必要があります。\r\n続行するには、一旦この管理セッションを終了し、サーバー コンピュータ上で SoftEther VPN サーバー管理マネージャを起動してから、localhost に対して接続して、設定を続行してください。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4,7 +4,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Tue Sep 15 14:39:53 2015
/* at Tue Oct 06 14:56:43 2015
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)

View File

@ -6,7 +6,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Tue Sep 15 14:39:53 2015
/* at Tue Oct 06 14:56:43 2015
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)

View File

@ -4,7 +4,7 @@
/* File created by MIDL compiler version 7.00.0500 */
/* at Tue Sep 15 14:39:53 2015
/* at Tue Oct 06 14:56:43 2015
*/
/* Compiler settings for .\vpnweb.idl:
Oicf, W1, Zp8, env=Win32 (32b run)