From 1bdd9a92bcd97b55d0863a01202d872e16c4b32d Mon Sep 17 00:00:00 2001 From: Evengard Date: Mon, 27 Apr 2020 21:43:40 +0300 Subject: [PATCH 01/13] Adding timeout propagation from user policy in PPP sessions (including L2TP and SSTP). --- src/Cedar/Proto_L2TP.c | 20 ++++++++++++++++++-- src/Cedar/Proto_L2TP.h | 1 + src/Cedar/Proto_PPP.c | 40 +++++++++++++++++++++++++++++++++++----- src/Cedar/Proto_PPP.h | 15 +++++++++++---- src/Cedar/Proto_SSTP.c | 14 ++++++++++++-- src/Cedar/Proto_SSTP.h | 3 ++- 6 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/Cedar/Proto_L2TP.c b/src/Cedar/Proto_L2TP.c index 960103ca..edf1b94f 100644 --- a/src/Cedar/Proto_L2TP.c +++ b/src/Cedar/Proto_L2TP.c @@ -1995,6 +1995,7 @@ UINT CalcL2TPMss(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s) // Start the L2TP thread void StartL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s) { + PPP_SESSION* underlyingSession; // Validate arguments if (l2tp == NULL || t == NULL || s == NULL) { @@ -2023,9 +2024,11 @@ void StartL2TPThread(L2TP_SERVER *l2tp, L2TP_TUNNEL *t, L2TP_SESSION *s) } // Create a PPP thread - s->Thread = NewPPPSession(l2tp->Cedar, &t->ClientIp, t->ClientPort, &t->ServerIp, t->ServerPort, + underlyingSession = NewPPPSession(l2tp->Cedar, &t->ClientIp, t->ClientPort, &t->ServerIp, t->ServerPort, s->TubeSend, s->TubeRecv, L2TP_IPC_POSTFIX, tmp, t->HostName, l2tp->CryptName, CalcL2TPMss(l2tp, t, s)); + s->Thread = underlyingSession->SessionThread; + s->PPPSession = underlyingSession; } } @@ -2122,8 +2125,21 @@ void L2TPProcessInterrupts(L2TP_SERVER *l2tp) { L2TP_TUNNEL *t = LIST_DATA(l2tp->TunnelList, i); LIST *delete_session_list = NULL; + UINT64 l2tpTimeout = L2TP_TUNNEL_TIMEOUT; - if ((l2tp->Now >= (t->LastRecvTick + (UINT64)L2TP_TUNNEL_TIMEOUT)) && t->Timedout == false) + // If we got on ANY session a higher timeout than the default L2TP tunnel timeout, increase it + for (i = 0; i < LIST_NUM(t->SessionList); i++) + { + L2TP_SESSION* s = LIST_DATA(t->SessionList, i); + + if (s->PPPSession != NULL && s->PPPSession->DataTimeout > l2tpTimeout) + { + l2tpTimeout = s->PPPSession->DataTimeout; + } + } + + + if ((l2tp->Now >= (t->LastRecvTick + (UINT64)l2tpTimeout)) && t->Timedout == false) { // Disconnect the tunnel forcibly if data can not be received for a certain period of time t->Timedout = true; diff --git a/src/Cedar/Proto_L2TP.h b/src/Cedar/Proto_L2TP.h index 1cd9767b..9d83f66b 100644 --- a/src/Cedar/Proto_L2TP.h +++ b/src/Cedar/Proto_L2TP.h @@ -169,6 +169,7 @@ struct L2TP_SESSION UINT64 DisconnectTimeout; // Disconnection completion time-out bool HasThread; // Whether have a thread THREAD *Thread; // Thread + PPP_SESSION* PPPSession; // Underlying PPP session TUBE *TubeSend; // Tube of PPP to L2TP direction TUBE *TubeRecv; // Tube of L2TP to PPP direction UINT PseudowireType; // Type of L2TPv3 virtual line diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 1bf4528f..cee81ad6 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -386,13 +386,22 @@ void PPPThread(THREAD *thread, void *param) } // Time-out inspection - if ((p->LastRecvTime + (UINT64)PPP_DATA_TIMEOUT) <= now) + if ((p->LastRecvTime + (UINT64)p->DataTimeout) <= now) { // Communication time-out occurs PPPLog(p, "LP_DATA_TIMEOUT"); break; } + // Maximum PPP session time of the user reached inspection + if (p->UserConnectionTick != 0 && p->UserConnectionTimeout != 0 && + p->UserConnectionTick + p->UserConnectionTimeout <= now) + { + // User connection time-out occurs + PPPLog(p, "LP_USER_TIMEOUT"); + break; + } + // Terminate if the PPP disconnected if (p->IsTerminateReceived) { @@ -444,7 +453,7 @@ void PPPThread(THREAD *thread, void *param) // Entry point // Create a new PPP session -THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss) +PPP_SESSION *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss) { PPP_SESSION *p; THREAD *t; @@ -474,6 +483,10 @@ THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ p->MsChapV2_ErrorCode = 691; p->EapClient = NULL; + p->DataTimeout = PPP_DATA_TIMEOUT; + p->PacketRecvTimeout = PPP_PACKET_RECV_TIMEOUT; + p->UserConnectionTimeout = 0; + p->Cedar = cedar; AddRef(cedar->ref); @@ -510,7 +523,9 @@ THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ // Thread creation t = NewThread(PPPThread, p); - return t; + p->SessionThread = t; + + return p; } // PPP processing functions @@ -1292,6 +1307,13 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) if (ipc != NULL) { p->Ipc = ipc; + + // Setting user timeouts + p->PacketRecvTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000 * 3 / 4; // setting to 3/4 of the user timeout + p->DataTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000; + p->UserConnectionTimeout = (UINT64)p->Ipc->Policy->AutoDisconnect * 1000; + p->UserConnectionTick = Tick64(); + p->AuthOk = true; } else @@ -1889,7 +1911,7 @@ bool PPPSendAndRetransmitRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c) resend->Id = pp->Lcp->Id; resend->Packet = pp; resend->ResendTime = now + PPP_PACKET_RESEND_INTERVAL; - resend->TimeoutTime = now + PPP_PACKET_RECV_TIMEOUT; + resend->TimeoutTime = now + p->PacketRecvTimeout; Add(p->SentReqPacketList, resend); @@ -1946,7 +1968,7 @@ LABEL_LOOP: if (async == false) { - d = TubeRecvSync(p->TubeRecv, PPP_PACKET_RECV_TIMEOUT); + d = TubeRecvSync(p->TubeRecv, p->PacketRecvTimeout); } else { @@ -2499,9 +2521,17 @@ bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION* p, PPP_PACKET* pp) { p->Ipc = ipc; + // Setting user timeouts + p->PacketRecvTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000 * 3 / 4; // setting to 3/4 of the user timeout + p->DataTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000; + p->UserConnectionTimeout = (UINT64)p->Ipc->Policy->AutoDisconnect * 1000; + p->UserConnectionTick = Tick64(); + Copy(p->MsChapV2_ServerResponse, ipc->MsChapV2_ServerResponse, 20); ok = true; + + p->AuthOk = true; } } else diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index afd9bfd8..79c338e9 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -32,11 +32,11 @@ //// Constants // Time-out value -#define PPP_PACKET_RECV_TIMEOUT (30 * 1000) // Timeout until the next packet is received -#define PPP_PACKET_RESEND_INTERVAL (5 * 1000) // Retransmission interval of the last packet +#define PPP_PACKET_RECV_TIMEOUT (15 * 1000) // Timeout until the next packet is received (3/4 of default policy) +#define PPP_PACKET_RESEND_INTERVAL (3 * 1000) // Retransmission interval of the last packet #define PPP_TERMINATE_TIMEOUT 2000 // Timeout value to complete disconnection after requesting to disconnect in the PPP #define PPP_ECHO_SEND_INTERVAL 4792 // Transmission interval of PPP Echo Request -#define PPP_DATA_TIMEOUT (60 * 1000) // Communication time-out +#define PPP_DATA_TIMEOUT (20 * 1000) // Communication time-out (from default policy) // MRU #define PPP_MRU_DEFAULT 1500 // Default value @@ -238,6 +238,13 @@ struct PPP_SESSION PPP_PACKET *CurrentPacket; LIST *DelayedPackets; + + UINT64 PacketRecvTimeout; + UINT64 DataTimeout; + UINT64 UserConnectionTimeout; + UINT64 UserConnectionTick; + + THREAD* SessionThread; // Thread of the PPP session }; @@ -248,7 +255,7 @@ struct PPP_SESSION void PPPThread(THREAD *thread, void *param); // Entry point -THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss); +PPP_SESSION *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss); // PPP processing functions bool PPPRejectUnsupportedPacket(PPP_SESSION *p, PPP_PACKET *pp); diff --git a/src/Cedar/Proto_SSTP.c b/src/Cedar/Proto_SSTP.c index cd9c7e86..83abc3bf 100644 --- a/src/Cedar/Proto_SSTP.c +++ b/src/Cedar/Proto_SSTP.c @@ -97,6 +97,8 @@ void SstpProcessControlPacket(SSTP_SERVER *s, SSTP_PACKET *p) // Process the SSTP received data packet void SstpProcessDataPacket(SSTP_SERVER *s, SSTP_PACKET *p) { + PPP_SESSION* underlyingSession; + // Validate arguments if (s == NULL || p == NULL || p->IsControl) { @@ -108,9 +110,11 @@ void SstpProcessDataPacket(SSTP_SERVER *s, SSTP_PACKET *p) if (s->PPPThread == NULL) { // Create a thread to initialize the new PPP module - s->PPPThread = NewPPPSession(s->Cedar, &s->ClientIp, s->ClientPort, &s->ServerIp, s->ServerPort, + underlyingSession = NewPPPSession(s->Cedar, &s->ClientIp, s->ClientPort, &s->ServerIp, s->ServerPort, s->TubeSend, s->TubeRecv, SSTP_IPC_POSTFIX, SSTP_IPC_CLIENT_NAME, s->ClientHostName, s->ClientCipherName, 0); + s->PPPSession = underlyingSession; + s->PPPThread = underlyingSession->SessionThread; } // Pass the received data to the PPP module @@ -177,6 +181,7 @@ void SstpSendPacket(SSTP_SERVER *s, SSTP_PACKET *p) // Process the timer interrupt void SstpProcessInterrupt(SSTP_SERVER *s) { + UINT64 sstpTimeout = SSTP_TIMEOUT; // Validate arguments if (s == NULL) { @@ -261,7 +266,12 @@ void SstpProcessInterrupt(SSTP_SERVER *s) } } - if ((s->LastRecvTick + (UINT64)SSTP_TIMEOUT) <= s->Now) + if (s->PPPSession != NULL && s->PPPSession->DataTimeout > sstpTimeout) + { + sstpTimeout = s->PPPSession->DataTimeout; + } + + if ((s->LastRecvTick + sstpTimeout) <= s->Now) { // Disconnect the SSTP because a timeout occurred SstpAbort(s); diff --git a/src/Cedar/Proto_SSTP.h b/src/Cedar/Proto_SSTP.h index ed722734..522c0056 100644 --- a/src/Cedar/Proto_SSTP.h +++ b/src/Cedar/Proto_SSTP.h @@ -16,7 +16,7 @@ #define SSTP_IPC_POSTFIX "SSTP" #define SSTP_ECHO_SEND_INTERVAL_MIN 2500 // Transmission interval of Echo Request (minimum) #define SSTP_ECHO_SEND_INTERVAL_MAX 4792 // Transmission interval of Echo Request (maximum) -#define SSTP_TIMEOUT 10000 // Communication time-out of SSTP +#define SSTP_TIMEOUT 20 * 1000 // Communication time-out of SSTP (from default policy) // SSTP Message Type #define SSTP_MSG_CALL_CONNECT_REQUEST 0x0001 @@ -116,6 +116,7 @@ struct SSTP_SERVER UINT64 LastRecvTick; // Tick when some data has received at the end bool FlushRecvTube; // Flag whether to flush the reception tube UINT EstablishedCount; // Number of session establishment + PPP_SESSION* PPPSession; // Underlying PPP Session }; From aa0ec4343cf72cfd38fbf1126bf810b373de5947 Mon Sep 17 00:00:00 2001 From: Evengard Date: Mon, 27 Apr 2020 22:18:57 +0300 Subject: [PATCH 02/13] Fixing errors as per static analysis --- src/Cedar/Proto_PPP.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index cee81ad6..6323fed8 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -744,11 +744,11 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req USHORT* protocol = pp->Lcp->Data; if (*protocol == PPP_PROTOCOL_IPCP || *protocol == PPP_PROTOCOL_IP) { - p->IPv4_State == PPP_PROTO_STATUS_REJECTED; + p->IPv4_State = PPP_PROTO_STATUS_REJECTED; } if (*protocol == PPP_PROTOCOL_IPV6CP || *protocol == PPP_PROTOCOL_IPV6) { - p->IPv6_State == PPP_PROTO_STATUS_REJECTED; + p->IPv6_State = PPP_PROTO_STATUS_REJECTED; } } } @@ -1031,7 +1031,7 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re return true; } - p->IPv4_State == PPP_PROTO_STATUS_CONFIG; + p->IPv4_State = PPP_PROTO_STATUS_CONFIG; PPPGetIPAddressValueFromLCP(req->Lcp, PPP_IPCP_OPTION_IP, &prevAddrStruct); prevAddr = IPToUINT(&prevAddrStruct); From a65c436e8f033561f363a284e4f6313e1378da9f Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 01:54:03 +0300 Subject: [PATCH 03/13] Writing skeleton for EAP-TLS implementation --- src/Cedar/CedarType.h | 1 + src/Cedar/Proto_PPP.c | 49 ++++++++++++++++++++++++++++++++++++++++++- src/Cedar/Proto_PPP.h | 49 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/Cedar/CedarType.h b/src/Cedar/CedarType.h index 27762cbb..2c4bd64a 100644 --- a/src/Cedar/CedarType.h +++ b/src/Cedar/CedarType.h @@ -500,6 +500,7 @@ typedef struct PPP_IPOPTION PPP_IPOPTION; typedef struct PPP_IPV6OPTION PPP_IPV6OPTION; typedef struct PPP_REQUEST_RESEND PPP_REQUEST_RESEND; typedef struct PPP_DELAYED_PACKET PPP_DELAYED_PACKET; +typedef struct PPP_EAP PPP_EAP; // ============================================================== diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 6323fed8..9f4548f9 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -706,6 +706,9 @@ bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req) case PPP_PROTOCOL_IPV6CP: Debug("IPv6CP to be implemented\n"); break; + case PPP_PROTOCOL_EAP: + return PPPProcessEAPResponsePacket(p, pp, req); + break; default: Debug("We received a response for an unsupported protocol??? Should be filtered out already! protocol = 0x%x, code = 0x%x\n", pp->Protocol, pp->Lcp->Code); PPPSetStatus(p, PPP_STATUS_FAIL); @@ -1061,6 +1064,31 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re return false; } +// Process EAP responses +bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req) +{ + PPP_EAP* eap_packet = pp->Lcp->Data; + switch (eap_packet->Type) + { + case PPP_EAP_TYPE_IDENTITY: + /// TODO: implement identity response processing + break; + case PPP_EAP_TYPE_NOTIFICATION: + // Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here... + break; + case PPP_EAP_TYPE_NAK: + /// TODO: implement alternative EAP protocol selection based on received NAK + break; + case PPP_EAP_TYPE_TLS: + /// TODO: implement EAP-TLS protocol here + break; + default: + Debug("We got an unexpected EAP response packet! Ignoring...\n"); + break; + } + return false; +} + // Processes request packets bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) @@ -1086,6 +1114,9 @@ bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) PPPRejectUnsupportedPacketEx(p, pp, true); Debug("IPv6CP to be implemented\n"); break; + case PPP_PROTOCOL_EAP: + return PPPProcessEAPRequestPacket(p, pp); + break; default: Debug("Unsupported protocols should be already filtered out! protocol = 0x%x, code = 0x%x\n", pp->Protocol, pp->Lcp->Code); return false; @@ -1711,6 +1742,13 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) return ok; } +// Process EAP request packets +bool PPPProcessEAPRequestPacket(PPP_SESSION* p, PPP_PACKET* pp) +{ + /// TODO: to implement + return false; +} + // LCP option based packets utility bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET* pp) { @@ -2270,7 +2308,7 @@ PPP_PACKET *ParsePPPPacket(void *data, UINT size) size -= 2; buf += 2; - if (pp->Protocol == PPP_PROTOCOL_LCP || pp->Protocol == PPP_PROTOCOL_PAP || pp->Protocol == PPP_PROTOCOL_CHAP || pp->Protocol == PPP_PROTOCOL_IPCP || pp->Protocol == PPP_PROTOCOL_IPV6CP) + if (pp->Protocol == PPP_PROTOCOL_LCP || pp->Protocol == PPP_PROTOCOL_PAP || pp->Protocol == PPP_PROTOCOL_CHAP || pp->Protocol == PPP_PROTOCOL_IPCP || pp->Protocol == PPP_PROTOCOL_IPV6CP || pp->Protocol == PPP_PROTOCOL_EAP) { pp->IsControl = true; } @@ -2843,6 +2881,13 @@ bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip) return true; } +// EAP packet utilities +bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT32 datasize) +{ + /// TODO: to implement + return false; +} + // Other packet utilities // Get the option value @@ -3367,3 +3412,5 @@ char *MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO *d, LIST *password_list) return NULL; } + + diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index 79c338e9..34be32da 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -21,11 +21,14 @@ #define PPP_CHAP_CODE_IS_REQUEST(c) ((c) == PPP_CHAP_CODE_CHALLENGE || (c) == PPP_CHAP_CODE_SUCCESS || (c) == PPP_CHAP_CODE_FAILURE) #define PPP_CHAP_CODE_IS_RESPONSE(c) ((c) == PPP_CHAP_CODE_RESPONSE) -#define PPP_CODE_IS_RESPONSE(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_RESPONSE(c))) -#define PPP_CODE_IS_REQUEST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_REQUEST(c))) +#define PPP_EAP_CODE_IS_REQUEST(c) ((c) == PPP_EAP_CODE_REQUEST || (c) == PPP_EAP_CODE_SUCCESS || (c) == PPP_EAP_CODE_FAILURE) // We treat SUCCESS and FAILURE as requests because they affect global state of the EAP protocol +#define PPP_EAP_CODE_IS_RESPONSE(c) ((c) == PPP_EAP_CODE_RESPONSE) + +#define PPP_CODE_IS_RESPONSE(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_RESPONSE(c))) +#define PPP_CODE_IS_REQUEST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_REQUEST(c))) #define PPP_CODE_IS_WITH_OPTION_LIST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_WITH_OPTION_LIST(c)) || false) -#define PPP_IS_SUPPORTED_PROTOCOL(p) ((p) == PPP_PROTOCOL_LCP || (p) == PPP_PROTOCOL_PAP || (p) == PPP_PROTOCOL_CHAP || (p) == PPP_PROTOCOL_IPCP || (p) == PPP_PROTOCOL_IPV6CP || (p) == PPP_PROTOCOL_IP || (p) == PPP_PROTOCOL_IPV6) +#define PPP_IS_SUPPORTED_PROTOCOL(p) ((p) == PPP_PROTOCOL_LCP || (p) == PPP_PROTOCOL_PAP || (p) == PPP_PROTOCOL_CHAP || (p) == PPP_PROTOCOL_IPCP || (p) == PPP_PROTOCOL_IPV6CP || (p) == PPP_PROTOCOL_IP || (p) == PPP_PROTOCOL_IPV6 || (p) == PPP_PROTOCOL_EAP ) #define PPP_STATUS_IS_UNAVAILABLE(c) ((c) == PPP_STATUS_FAIL || (c) == PPP_STATUS_AUTH_FAIL || (c) == PPP_STATUS_CLOSING || (c) == PPP_STATUS_CLOSING_WAIT || (c) == PPP_STATUS_CLOSED) @@ -48,6 +51,7 @@ #define PPP_PROTOCOL_PAP 0xc023 #define PPP_PROTOCOL_IPCP 0x8021 #define PPP_PROTOCOL_CHAP 0xc223 +#define PPP_PROTOCOL_EAP 0xc227 #define PPP_PROTOCOL_IPV6CP 0x8057 // PPP protocol (for transfer) @@ -93,6 +97,18 @@ // IPV6CP option type #define PPP_IPV6CP_OPTION_IID 1 +// EAP codes +#define PPP_EAP_CODE_REQUEST 1 +#define PPP_EAP_CODE_RESPONSE 2 +#define PPP_EAP_CODE_SUCCESS 3 +#define PPP_EAP_CODE_FAILURE 4 + +// EAP types +#define PPP_EAP_TYPE_IDENTITY 1 +#define PPP_EAP_TYPE_NOTIFICATION 2 +#define PPP_EAP_TYPE_NAK 3 +#define PPP_EAP_TYPE_TLS 13 + // Authentication protocol #define PPP_LCP_AUTH_PAP PPP_PROTOCOL_PAP #define PPP_LCP_AUTH_CHAP PPP_PROTOCOL_CHAP @@ -164,6 +180,28 @@ struct PPP_OPTION UINT AltDataSize; // Alternate data size }; +// PPP EAP packet +// EAP is a subset of LCP, sharing Code and Id. The Data field is then mapped to this structure +struct PPP_EAP +{ + UCHAR Type; + union { + UCHAR Data[253]; // LCP Data field = 254 minus 1 byte for Type field + struct PPP_EAP_TLS + { + UCHAR Flags; + union { + UCHAR TlsDataWithoutLength[252]; // EAP-TLS structure size 1 (Flags) + 252 = 253 + struct + { + UINT32 Length; + UCHAR Data[248]; // EAP-TLS structure size 1 (Flags) + 4 (TlsSize) + 248 = 253 + } TlsDataWithLength; + }; + } Tls; + }; +}; + // PPP request resend struct PPP_REQUEST_RESEND { @@ -267,11 +305,13 @@ bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); +bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req); // Request packets bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); +bool PPPProcessEAPRequestPacket(PPP_SESSION* p, PPP_PACKET* pp); // LCP option based packets utility bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET *pp); @@ -281,7 +321,6 @@ bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate); bool PPPAckLCPOptions(PPP_SESSION *p, PPP_PACKET *pp); bool PPPAckLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate); - // PPP networking functions // Send packets bool PPPSendAndRetransmitRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c); @@ -312,6 +351,8 @@ bool PPPGetIPOptionFromLCP(PPP_IPOPTION *o, PPP_LCP *c); bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify); bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip); bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify); +// EAP packet utilities +bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT32 datasize); // Other packet utilities PPP_OPTION *PPPGetOptionValue(PPP_LCP *c, UCHAR type); bool IsHubExistsWithLock(CEDAR *cedar, char *hubname); From 9f2a5cecf3300dd398ed44fd4f74834655435f84 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 09:38:08 +0300 Subject: [PATCH 04/13] Preliminary (untested) EAP-TLS implementation --- src/Cedar/CedarType.h | 1 + src/Cedar/Proto_PPP.c | 467 ++++++++++++++++++++++++++++++++++++++---- src/Cedar/Proto_PPP.h | 35 +++- 3 files changed, 457 insertions(+), 46 deletions(-) diff --git a/src/Cedar/CedarType.h b/src/Cedar/CedarType.h index 2c4bd64a..e3124a8c 100644 --- a/src/Cedar/CedarType.h +++ b/src/Cedar/CedarType.h @@ -501,6 +501,7 @@ typedef struct PPP_IPV6OPTION PPP_IPV6OPTION; typedef struct PPP_REQUEST_RESEND PPP_REQUEST_RESEND; typedef struct PPP_DELAYED_PACKET PPP_DELAYED_PACKET; typedef struct PPP_EAP PPP_EAP; +typedef struct PPP_EAP_TLS_CONTEXT PPP_EAP_TLS_CONTEXT; // ============================================================== diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 9f4548f9..c1586d51 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -35,6 +35,8 @@ void PPPThread(THREAD *thread, void *param) p->IPv4_State = PPP_PROTO_STATUS_CLOSED; p->IPv6_State = PPP_PROTO_STATUS_CLOSED; + p->Eap_Protocol = PPP_UNSPECIFIED; + p->Mru1 = p->Mru2 = PPP_MRU_DEFAULT; p->RecvPacketList = NewList(NULL); p->SentReqPacketList = NewList(NULL); @@ -229,6 +231,45 @@ void PPPThread(THREAD *thread, void *param) Debug("Unprocessed and unrejected packet, protocol = 0x%x\n", p->CurrentPacket->Protocol); } } + else if (p->PPPStatus == PPP_STATUS_BEFORE_AUTH && p->AuthProtocol == PPP_PROTOCOL_EAP) + { + PPP_LCP* lcpEap; + PPP_EAP* eapPacket; + UCHAR* welcomeMessage = "Welcome to the SoftEther VPN server!"; + UCHAR flags = 0; + // We got to start EAP when we got no LCP packets from the client on previous iteration + // which means we parsed all the client requests and responses + + switch (p->Eap_Protocol) + { + case PPP_EAP_TYPE_TLS: + // Sending TLS Start... + flags |= 1 << 2; + lcpEap = BuildEAPTlsRequest(p->Eap_PacketId++, 0, flags); + PPPSetStatus(p, PPP_STATUS_AUTHENTICATING); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcpEap)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + break; + case PPP_EAP_TYPE_IDENTITY: + default: // We treat the unspecified protocol as the IDENTITY protocol + p->Eap_Protocol = PPP_EAP_TYPE_IDENTITY; + lcpEap = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId++, PPP_EAP_TYPE_IDENTITY, sizeof(welcomeMessage)); + eapPacket = lcpEap->Data; + Copy(eapPacket->Data, welcomeMessage, sizeof(welcomeMessage)); + PPPSetStatus(p, PPP_STATUS_AUTHENTICATING); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcpEap)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + break; + } + } else if (p->PPPStatus == PPP_STATUS_BEFORE_AUTH && p->AuthProtocol == PPP_PROTOCOL_CHAP) { // We got to start CHAP when we got no LCP packets from the client on previous iteration @@ -247,14 +288,12 @@ void PPPThread(THREAD *thread, void *param) if (p->PPPStatus == PPP_STATUS_CONNECTED && !authReqSent) { - // MSCHAPv2 code + // EAP code PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); - UCHAR ms_chap_v2_code[3]; - WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); - ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; + USHORT eap_code = PPP_LCP_AUTH_EAP; - Debug("Request MSCHAPv2\n"); - Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, ms_chap_v2_code, sizeof(ms_chap_v2_code))); + Debug("Request EAP\n"); + Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &eap_code, sizeof(eap_code))); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_LCP, c)) { PPPSetStatus(p, PPP_STATUS_FAIL); @@ -368,7 +407,7 @@ void PPPThread(THREAD *thread, void *param) } else { - WaitForTubes(tubes, 1, 100); + WaitForTubes(tubes, 1, 1000); // Increasing timeout to make the ticks a bit slower } if (IsTubeConnected(p->TubeRecv) == false || IsTubeConnected(p->TubeSend) == false) @@ -479,7 +518,7 @@ PPP_SESSION *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *se p = ZeroMalloc(sizeof(PPP_SESSION)); p->EnableMSCHAPv2 = true; - p->AuthProtocol = NULL; + p->AuthProtocol = PPP_UNSPECIFIED; p->MsChapV2_ErrorCode = 691; p->EapClient = NULL; @@ -825,7 +864,37 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req WHERE; return false; } - if (opt->DataSize == sizeof(ms_chap_v2_code) && Cmp(opt->Data, ms_chap_v2_code, opt->DataSize) == 0) + if (opt->DataSize == sizeof(USHORT) && *((USHORT*)(opt->Data)) == Endian16(PPP_LCP_AUTH_EAP)) + { + // Try to request MS-CHAPv2 then + if (!isAccepted) + { + UINT64 offer = 0; + PPP_LCP* c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); + UCHAR ms_chap_v2_code[3]; + + WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); + ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; + + Copy(&offer, ms_chap_v2_code, sizeof(ms_chap_v2_code)); + Debug("NACK proto with code = 0x%x, cypher = 0x%x, offered cypher = 0x%x\n", pp->Lcp->Code, *((USHORT*)(opt->Data)), offer); + Debug("Request MSCHAPv2\n"); + Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &ms_chap_v2_code, sizeof(ms_chap_v2_code))); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_LCP, c)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } + else + { + p->AuthProtocol = PPP_PROTOCOL_EAP; + Debug("Setting BEFORE_AUTH from ACK on LCP response parse on EAP accept\n"); + PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH); + } + } + else if (opt->DataSize == sizeof(ms_chap_v2_code) && Cmp(opt->Data, ms_chap_v2_code, opt->DataSize) == 0) { // Try to request PAP then if (!isAccepted || !p->EnableMSCHAPv2) @@ -844,7 +913,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req return false; } } - else if (p->AuthProtocol == NULL) + else if (p->AuthProtocol == PPP_UNSPECIFIED) { p->AuthProtocol = PPP_PROTOCOL_CHAP; Debug("Setting BEFORE_AUTH from ACK on LCP response parse on CHAP accept\n"); @@ -866,7 +935,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req WHERE; return false; } - else if (p->AuthProtocol == NULL) + else if (p->AuthProtocol == PPP_UNSPECIFIED) { p->AuthProtocol = PPP_PROTOCOL_PAP; Debug("Setting BEFORE_AUTH from ACK on LCP response parse on PAP accept\n"); @@ -1067,24 +1136,58 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re // Process EAP responses bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req) { - PPP_EAP* eap_packet = pp->Lcp->Data; - switch (eap_packet->Type) + if (pp->Lcp->DataSize >= 1) { - case PPP_EAP_TYPE_IDENTITY: - /// TODO: implement identity response processing - break; - case PPP_EAP_TYPE_NOTIFICATION: - // Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here... - break; - case PPP_EAP_TYPE_NAK: - /// TODO: implement alternative EAP protocol selection based on received NAK - break; - case PPP_EAP_TYPE_TLS: - /// TODO: implement EAP-TLS protocol here - break; - default: - Debug("We got an unexpected EAP response packet! Ignoring...\n"); - break; + PPP_EAP* eap_packet = pp->Lcp->Data; + UINT eap_datasize = pp->Lcp->DataSize - 1; + UINT64 offer = 0; + PPP_LCP* c; + UCHAR ms_chap_v2_code[3]; + + WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); + ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; + + switch (eap_packet->Type) + { + case PPP_EAP_TYPE_IDENTITY: + Copy(p->Eap_Identity, eap_packet->Data, MIN(MAX_SIZE, eap_datasize)); + // As we received the identity packet, we switch back to BEFORE_AUTH and switch to the EAP_TLS proto to send the TlsStart packet on the next tick + p->Eap_Protocol = PPP_EAP_TYPE_TLS; + PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH); + break; + case PPP_EAP_TYPE_NOTIFICATION: + // Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here... + break; + case PPP_EAP_TYPE_NAK: + /// TODO: implement alternative EAP protocol selection based on received NAK + // For now just fallback to auth protocol selection to try to select MSCHAP or PAP + Debug("Got a EAP_NAK, abandoning EAP protocol\n"); + PPPRejectUnsupportedPacketEx(p, pp, true); + PPPSetStatus(p, PPP_STATUS_CONNECTED); + + c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); + Copy(&offer, ms_chap_v2_code, sizeof(ms_chap_v2_code)); + Debug("Request MSCHAPv2 from EAP NAK\n"); + Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &ms_chap_v2_code, sizeof(ms_chap_v2_code))); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_LCP, c)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + break; + case PPP_EAP_TYPE_TLS: + PPPProcessEAPTlsResponse(p, eap_packet, eap_datasize); + break; + default: + Debug("We got an unexpected EAP response packet! Ignoring...\n"); + break; + } + } + else + { + // Means we got a Success or Failure packet... + Debug("We got a CODE %i from client with zero size EAP structure, that shouldn't be happening!\n", pp->Lcp->Code); } return false; } @@ -1134,6 +1237,7 @@ bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) USHORT NegotiatedMRU = PPP_UNSPECIFIED; // MSCHAPv2 code UCHAR ms_chap_v2_code[3]; + USHORT eap_code = PPP_LCP_AUTH_EAP; WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; @@ -1148,22 +1252,27 @@ bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) { case PPP_LCP_OPTION_AUTH: t->IsSupported = true; - if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == Endian16(PPP_LCP_AUTH_PAP) && p->AuthProtocol != PPP_PROTOCOL_CHAP) + if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == Endian16(PPP_LCP_AUTH_EAP) && p->AuthProtocol == PPP_UNSPECIFIED) + { + t->IsAccepted = true; + NegotiatedAuthProto = PPP_PROTOCOL_EAP; + } + else if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == Endian16(PPP_LCP_AUTH_PAP) && p->AuthProtocol == PPP_UNSPECIFIED) { t->IsAccepted = true; NegotiatedAuthProto = PPP_PROTOCOL_PAP; } - else if (t->DataSize == sizeof(ms_chap_v2_code) && Cmp(t->Data, ms_chap_v2_code, t->DataSize) == 0) + else if (t->DataSize == sizeof(ms_chap_v2_code) && Cmp(t->Data, ms_chap_v2_code, t->DataSize) == 0 && p->AuthProtocol == PPP_UNSPECIFIED) { t->IsAccepted = true; NegotiatedAuthProto = PPP_PROTOCOL_CHAP; } else { - // We're recommending MSCHAPv2 by default as a more secure algo + // We're recommending EAP by default as a more secure algo t->IsAccepted = false; - t->AltDataSize = sizeof(ms_chap_v2_code); - Copy(t->AltData, ms_chap_v2_code, sizeof(ms_chap_v2_code)); + t->AltDataSize = sizeof(eap_code); + Copy(t->AltData, &eap_code, sizeof(eap_code)); } break; case PPP_LCP_OPTION_MRU: @@ -1219,7 +1328,7 @@ bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) if (NegotiatedAuthProto != PPP_UNSPECIFIED) { - if (p->AuthProtocol == NULL) + if (p->AuthProtocol == PPP_UNSPECIFIED) { p->AuthProtocol = NegotiatedAuthProto; PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH); @@ -1407,7 +1516,7 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) return false; } - + return p->AuthOk; } @@ -1701,7 +1810,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) // We will delay this packet ACK and send the server IP first, then wait for a reparse // it is kind of dirty but fixes issues on some clients (namely VPN Client Pro on Android) - if (p->IPv4_State == PPP_PROTO_STATUS_CLOSED && p->ClientAddressOption.ServerAddress != NULL && ok) + if (p->IPv4_State == PPP_PROTO_STATUS_CLOSED && p->ClientAddressOption.ServerAddress != 0 && ok) { PPP_LCP* c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); UINT ui = p->ClientAddressOption.ServerAddress; @@ -1745,7 +1854,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) // Process EAP request packets bool PPPProcessEAPRequestPacket(PPP_SESSION* p, PPP_PACKET* pp) { - /// TODO: to implement + Debug("We got an EAP request, which is weird...\n"); return false; } @@ -2882,12 +2991,273 @@ bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip) } // EAP packet utilities -bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT32 datasize) +bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSize) { - /// TODO: to implement + UCHAR* dataBuffer; + UINT dataSize; + UINT tlsLength = 0; + bool isFragmented = false; + PPP_LCP* lcp; + PPP_EAP* eap; + UCHAR flags; + UINT64 sizeLeft = 0; + if (eapTlsSize == 0) + { + // This is an EAP-TLS message ACK + if (p->Eap_TlsCtx.cachedBuffer != NULL && p->Eap_TlsCtx.cachedBufferSend == true) + { + // We got an ACK to transmit the next fragmented message + dataSize = p->Mru1 - 8 - 1 - 1; // Calculating the maximum payload size (without TlsLength) + sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBuffer); + sizeLeft -= p->Eap_TlsCtx.cachedBufferPntr - p->Eap_TlsCtx.cachedBuffer; + + flags = 1 << 1; // M flag + if (dataSize > sizeLeft) + { + dataSize = sizeLeft; + flags = 0; // Clearing the M flag because it is the last packet + } + lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); + eap = lcp->Data; + Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.cachedBufferPntr, dataSize); + p->Eap_TlsCtx.cachedBufferPntr += dataSize; + + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + + if (flags == 0) + { + // As it is the latest message, we need to cleanup + Free(p->Eap_TlsCtx.cachedBuffer); + p->Eap_TlsCtx.cachedBuffer = NULL; + p->Eap_TlsCtx.cachedBufferPntr = NULL; + p->Eap_TlsCtx.cachedBufferSend = false; + } + } + else + { + // It probably should be the final ACK on closed SSL pipe + SyncSslPipe(p->Eap_TlsCtx.SslPipe); + if (p->Eap_TlsCtx.clientCert.X != NULL) + { + IPC* ipc; + ETHERIP_ID d; + UINT error_code; + + PPPParseUsername(p->Cedar, p->Eap_Identity, &d); + + ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "", + &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, + p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL, + IPC_LAYER_3); + + if (ipc != NULL) + { + p->Ipc = ipc; + PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS); + + // Just send an EAP-Success + lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, p->Eap_PacketId++); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + return true; + } + else + { + PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); + lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId++); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + return false; + } + } + else + { + Debug("Weird ACK for no reason at all...\n"); + return false; + } + } + return true; + } + dataBuffer = eap_packet->Tls.TlsDataWithoutLength; + dataSize = eapTlsSize - 1; + if (eap_packet->Tls.Flags & 1) + { + dataBuffer = eap_packet->Tls.TlsDataWithLength.Data; + dataSize -= 4; + tlsLength = eap_packet->Tls.TlsDataWithLength.TlsLength; + } + if (eap_packet->Tls.Flags & 1 << 1) + { + isFragmented = true; + } + + if (p->PPPStatus == PPP_STATUS_AUTHENTICATING) + { + // First we initialize the SslPipe if it is not already inited + if (p->Eap_TlsCtx.SslPipe == NULL) + { + p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT); + p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.clientCert)); + } + + // If the current frame is fragmented, or it is a possible last of a fragmented series, bufferize it + if (isFragmented || p->Eap_TlsCtx.cachedBuffer != NULL) + { + if (p->Eap_TlsCtx.cachedBufferSend) + { + Debug("We got a weird packet when we have a sending only caching buffer, ignoring...\n"); + return false; + } + if (p->Eap_TlsCtx.cachedBuffer == NULL && tlsLength > 0) + { + p->Eap_TlsCtx.cachedBuffer = ZeroMalloc(MAX(dataSize, tlsLength)); + p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer; + } + else + { + Debug("We didn't get the tlsLength size! We're probably corrupt.\n"); + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBuffer); + sizeLeft -= p->Eap_TlsCtx.cachedBufferPntr - p->Eap_TlsCtx.cachedBuffer; + + Copy(p->Eap_TlsCtx.cachedBufferPntr, dataBuffer, MIN(dataSize, sizeLeft)); + + p->Eap_TlsCtx.cachedBufferPntr += MIN(dataSize, sizeLeft); + } + + // If we got a cached buffer, we should feed the FIFOs via it + if (p->Eap_TlsCtx.cachedBuffer != NULL) + { + dataBuffer = p->Eap_TlsCtx.cachedBuffer; + dataSize = GetMemSize(p->Eap_TlsCtx.cachedBuffer); + } + + // Just acknoweldge that we buffered the fragmented data + if (isFragmented) + { + PPP_LCP* lcp = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId++, PPP_EAP_TYPE_TLS, 0); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } + else + { + WriteFifo(p->Eap_TlsCtx.SslPipe->RawIn->SendFifo, dataBuffer, dataSize); + SyncSslPipe(p->Eap_TlsCtx.SslPipe); + // Delete the cached buffer after we fed it into the pipe + if (p->Eap_TlsCtx.cachedBuffer != NULL) + { + Free(p->Eap_TlsCtx.cachedBuffer); + p->Eap_TlsCtx.cachedBuffer = NULL; + p->Eap_TlsCtx.cachedBufferPntr = NULL; + } + + if (p->Eap_TlsCtx.SslPipe->IsDisconnected == false) + { + dataSize = FifoSize(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo); + // Do we need to send a fragmented packet? + if (dataSize > p->Mru1 - 8 - 1 - 1) + { + if (p->Eap_TlsCtx.cachedBuffer == NULL) + { + p->Eap_TlsCtx.cachedBuffer = ZeroMalloc(dataSize); + p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer; + } + p->Eap_TlsCtx.cachedBufferSend = true; + ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, p->Eap_TlsCtx.cachedBuffer, dataSize); + + // Now send data from the cached buffer with set fragmentation flag and also total TLS Size + tlsLength = dataSize; + dataSize = p->Mru1 - 8 - 1 - 1 - 4; // Calculating the maximum payload size (adjusting for including TlsLength) + flags = 1; // L flag + flags |= 1 << 1; // M flag + lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); + eap = lcp->Data; + eap->Tls.TlsDataWithLength.TlsLength = tlsLength; + Copy(eap->Tls.TlsDataWithLength.Data, p->Eap_TlsCtx.cachedBuffer, dataSize); + p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer + dataSize; + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } + else + { + lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, 0); + eap = lcp->Data; + ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, &(eap->Tls.TlsDataWithoutLength), dataSize); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } + } + } + } + else + { + Debug("Got an EAP_TLS packet when not authenticating, ignoring...\n"); + } return false; } +PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize) +{ + PPP_EAP* eap_packet; + PPP_LCP* lcp_packet; + UINT lcpDatasize; + lcpDatasize = datasize + sizeof(UCHAR); + eap_packet = ZeroMalloc(lcpDatasize); + eap_packet->Type = type; + lcp_packet = NewPPPLCP(code, id); + lcp_packet->Data = eap_packet; + lcp_packet->DataSize = lcpDatasize; + return lcp_packet; +} + +PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UCHAR flags) +{ + PPP_LCP* lcp_packet; + PPP_EAP* eap_packet; + UINT tls_datasize = datasize + sizeof(UCHAR); + if (flags & 1) + { + tls_datasize += sizeof(UINT32); + } + lcp_packet = BuildEAPPacketEx(code, id, type, tls_datasize); + eap_packet = lcp_packet->Data; + eap_packet->Tls.Flags = flags; + return lcp_packet; +} + +PPP_LCP* BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags) +{ + return BuildEAPTlsPacketEx(PPP_EAP_CODE_REQUEST, id, PPP_EAP_TYPE_TLS, datasize, flags); +} + // Other packet utilities // Get the option value @@ -2999,6 +3369,25 @@ void FreePPPSession(PPP_SESSION *p) p->TubeRecv->IntParam2 = p->DisconnectCauseDirection; } + // Freeing EAP-TLS context + if (p->Eap_TlsCtx.cachedBuffer != NULL) + { + Free(p->Eap_TlsCtx.cachedBuffer); + } + if (p->Eap_TlsCtx.SslPipe != NULL) + { + FreeSslPipe(p->Eap_TlsCtx.SslPipe); + } + if (p->Eap_TlsCtx.clientCert.X != NULL) + { + FreeX(p->Eap_TlsCtx.clientCert.X); + } + if (p->Eap_TlsCtx.Dh != NULL) + { + DhFree(p->Eap_TlsCtx.Dh); + } + + FreeTubeFlushList(p->FlushList); TubeDisconnect(p->TubeRecv); diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index 34be32da..69174074 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -21,8 +21,8 @@ #define PPP_CHAP_CODE_IS_REQUEST(c) ((c) == PPP_CHAP_CODE_CHALLENGE || (c) == PPP_CHAP_CODE_SUCCESS || (c) == PPP_CHAP_CODE_FAILURE) #define PPP_CHAP_CODE_IS_RESPONSE(c) ((c) == PPP_CHAP_CODE_RESPONSE) -#define PPP_EAP_CODE_IS_REQUEST(c) ((c) == PPP_EAP_CODE_REQUEST || (c) == PPP_EAP_CODE_SUCCESS || (c) == PPP_EAP_CODE_FAILURE) // We treat SUCCESS and FAILURE as requests because they affect global state of the EAP protocol -#define PPP_EAP_CODE_IS_RESPONSE(c) ((c) == PPP_EAP_CODE_RESPONSE) +#define PPP_EAP_CODE_IS_REQUEST(c) ((c) == PPP_EAP_CODE_REQUEST) +#define PPP_EAP_CODE_IS_RESPONSE(c) ((c) == PPP_EAP_CODE_RESPONSE || (c) == PPP_EAP_CODE_SUCCESS || (c) == PPP_EAP_CODE_FAILURE) #define PPP_CODE_IS_RESPONSE(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_RESPONSE(c))) #define PPP_CODE_IS_REQUEST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_REQUEST(c))) @@ -112,6 +112,7 @@ // Authentication protocol #define PPP_LCP_AUTH_PAP PPP_PROTOCOL_PAP #define PPP_LCP_AUTH_CHAP PPP_PROTOCOL_CHAP +#define PPP_LCP_AUTH_EAP PPP_PROTOCOL_EAP // Algorithm of CHAP #define PPP_CHAP_ALG_MS_CHAP_V2 0x81 @@ -182,26 +183,37 @@ struct PPP_OPTION // PPP EAP packet // EAP is a subset of LCP, sharing Code and Id. The Data field is then mapped to this structure +// We got 8 bytes of size before this structure struct PPP_EAP { UCHAR Type; union { - UCHAR Data[253]; // LCP Data field = 254 minus 1 byte for Type field + UCHAR Data[0]; struct PPP_EAP_TLS { UCHAR Flags; union { - UCHAR TlsDataWithoutLength[252]; // EAP-TLS structure size 1 (Flags) + 252 = 253 + UCHAR TlsDataWithoutLength[0]; struct { - UINT32 Length; - UCHAR Data[248]; // EAP-TLS structure size 1 (Flags) + 4 (TlsSize) + 248 = 253 + UINT32 TlsLength; + UCHAR Data[0]; } TlsDataWithLength; }; } Tls; }; }; +struct PPP_EAP_TLS_CONTEXT +{ + SSL_PIPE* SslPipe; + DH_CTX* Dh; + struct SslClientCertInfo clientCert; + UCHAR* cachedBuffer; + UCHAR* cachedBufferPntr; + bool cachedBufferSend; +}; + // PPP request resend struct PPP_REQUEST_RESEND { @@ -272,6 +284,12 @@ struct PPP_SESSION UINT IPv4_State; UINT IPv6_State; + // EAP contexts + UINT Eap_Protocol; // Current EAP Protocol used + UINT Eap_PacketId; // EAP Packet ID; + UCHAR Eap_Identity[MAX_SIZE]; // Received from client identity + PPP_EAP_TLS_CONTEXT Eap_TlsCtx; // Context information for EAP TLS. May be possibly reused for EAP TTLS? + LIST *SentReqPacketList; // Sent requests list PPP_PACKET *CurrentPacket; @@ -352,7 +370,10 @@ bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify); bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip); bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify); // EAP packet utilities -bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT32 datasize); +bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSize); +PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize); +PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UCHAR flags); +PPP_LCP* BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags); // Other packet utilities PPP_OPTION *PPPGetOptionValue(PPP_LCP *c, UCHAR type); bool IsHubExistsWithLock(CEDAR *cedar, char *hubname); From 24bd2b31986866025e98357b66bc02d580198530 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 10:11:01 +0300 Subject: [PATCH 05/13] Fixing up some errors --- src/Cedar/Proto_PPP.c | 115 ++++++++++++++++++++++-------------------- src/Cedar/Proto_PPP.h | 24 +++++++-- src/Mayaqua/Network.c | 2 +- src/Mayaqua/Network.h | 3 +- 4 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index c1586d51..50503ae3 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -236,7 +236,7 @@ void PPPThread(THREAD *thread, void *param) PPP_LCP* lcpEap; PPP_EAP* eapPacket; UCHAR* welcomeMessage = "Welcome to the SoftEther VPN server!"; - UCHAR flags = 0; + UCHAR flags = PPP_EAP_TLS_FLAG_NONE; // We got to start EAP when we got no LCP packets from the client on previous iteration // which means we parsed all the client requests and responses @@ -244,7 +244,7 @@ void PPPThread(THREAD *thread, void *param) { case PPP_EAP_TYPE_TLS: // Sending TLS Start... - flags |= 1 << 2; + flags |= PPP_EAP_TLS_FLAG_SSLSTARTED; lcpEap = BuildEAPTlsRequest(p->Eap_PacketId++, 0, flags); PPPSetStatus(p, PPP_STATUS_AUTHENTICATING); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcpEap)) @@ -290,7 +290,7 @@ void PPPThread(THREAD *thread, void *param) { // EAP code PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); - USHORT eap_code = PPP_LCP_AUTH_EAP; + USHORT eap_code = Endian16(PPP_LCP_AUTH_EAP); Debug("Request EAP\n"); Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &eap_code, sizeof(eap_code))); @@ -304,7 +304,7 @@ void PPPThread(THREAD *thread, void *param) if (p->PPPStatus == PPP_STATUS_AUTHENTICATING) { - Debug("Tick waiting for auth...\n"); + //Debug("Tick waiting for auth...\n"); } if (p->PPPStatus == PPP_STATUS_AUTH_FAIL) @@ -1252,12 +1252,12 @@ bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) { case PPP_LCP_OPTION_AUTH: t->IsSupported = true; - if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == Endian16(PPP_LCP_AUTH_EAP) && p->AuthProtocol == PPP_UNSPECIFIED) + if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == PPP_LCP_AUTH_EAP && p->AuthProtocol == PPP_UNSPECIFIED) { t->IsAccepted = true; NegotiatedAuthProto = PPP_PROTOCOL_EAP; } - else if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == Endian16(PPP_LCP_AUTH_PAP) && p->AuthProtocol == PPP_UNSPECIFIED) + else if (t->DataSize == sizeof(USHORT) && *((USHORT*)t->Data) == PPP_LCP_AUTH_PAP && p->AuthProtocol == PPP_UNSPECIFIED) { t->IsAccepted = true; NegotiatedAuthProto = PPP_PROTOCOL_PAP; @@ -3001,26 +3001,27 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi PPP_EAP* eap; UCHAR flags; UINT64 sizeLeft = 0; - if (eapTlsSize == 0) + Debug("Got EAP-TLS size=%i\n", eapTlsSize); + if (eapTlsSize == 1) { // This is an EAP-TLS message ACK - if (p->Eap_TlsCtx.cachedBuffer != NULL && p->Eap_TlsCtx.cachedBufferSend == true) + if (p->Eap_TlsCtx.cachedBufferSend != NULL) { // We got an ACK to transmit the next fragmented message dataSize = p->Mru1 - 8 - 1 - 1; // Calculating the maximum payload size (without TlsLength) - sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBuffer); - sizeLeft -= p->Eap_TlsCtx.cachedBufferPntr - p->Eap_TlsCtx.cachedBuffer; + sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBufferSend); + sizeLeft -= p->Eap_TlsCtx.cachedBufferSendPntr - p->Eap_TlsCtx.cachedBufferSend; - flags = 1 << 1; // M flag + flags = PPP_EAP_TLS_FLAG_FRAGMENTED; // M flag if (dataSize > sizeLeft) { dataSize = sizeLeft; - flags = 0; // Clearing the M flag because it is the last packet + flags = PPP_EAP_TLS_FLAG_NONE; // Clearing the M flag because it is the last packet } lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); eap = lcp->Data; - Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.cachedBufferPntr, dataSize); - p->Eap_TlsCtx.cachedBufferPntr += dataSize; + Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.cachedBufferSendPntr, dataSize); + p->Eap_TlsCtx.cachedBufferSendPntr += dataSize; if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { @@ -3028,14 +3029,14 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } + Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags); - if (flags == 0) + if (flags == PPP_EAP_TLS_FLAG_NONE) { // As it is the latest message, we need to cleanup - Free(p->Eap_TlsCtx.cachedBuffer); - p->Eap_TlsCtx.cachedBuffer = NULL; - p->Eap_TlsCtx.cachedBufferPntr = NULL; - p->Eap_TlsCtx.cachedBufferSend = false; + Free(p->Eap_TlsCtx.cachedBufferSend); + p->Eap_TlsCtx.cachedBufferSend = NULL; + p->Eap_TlsCtx.cachedBufferSendPntr = NULL; } } else @@ -3068,6 +3069,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } + Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize); return true; } else @@ -3080,6 +3082,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } + Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize); return false; } } @@ -3093,13 +3096,13 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi } dataBuffer = eap_packet->Tls.TlsDataWithoutLength; dataSize = eapTlsSize - 1; - if (eap_packet->Tls.Flags & 1) + if (eap_packet->Tls.Flags & PPP_EAP_TLS_FLAG_TLS_LENGTH) { dataBuffer = eap_packet->Tls.TlsDataWithLength.Data; dataSize -= 4; - tlsLength = eap_packet->Tls.TlsDataWithLength.TlsLength; + tlsLength = Endian32(eap_packet->Tls.TlsDataWithLength.TlsLength); } - if (eap_packet->Tls.Flags & 1 << 1) + if (eap_packet->Tls.Flags & PPP_EAP_TLS_FLAG_FRAGMENTED) { isFragmented = true; } @@ -3109,22 +3112,18 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi // First we initialize the SslPipe if it is not already inited if (p->Eap_TlsCtx.SslPipe == NULL) { + p->Eap_TlsCtx.clientCert.IgnorePreverifyErr = true; p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT); p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.clientCert)); } // If the current frame is fragmented, or it is a possible last of a fragmented series, bufferize it - if (isFragmented || p->Eap_TlsCtx.cachedBuffer != NULL) + if (isFragmented || p->Eap_TlsCtx.cachedBufferRecv != NULL) { - if (p->Eap_TlsCtx.cachedBufferSend) + if (p->Eap_TlsCtx.cachedBufferRecv == NULL && tlsLength > 0) { - Debug("We got a weird packet when we have a sending only caching buffer, ignoring...\n"); - return false; - } - if (p->Eap_TlsCtx.cachedBuffer == NULL && tlsLength > 0) - { - p->Eap_TlsCtx.cachedBuffer = ZeroMalloc(MAX(dataSize, tlsLength)); - p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer; + p->Eap_TlsCtx.cachedBufferRecv = ZeroMalloc(MAX(dataSize, tlsLength)); + p->Eap_TlsCtx.cachedBufferRecvPntr = p->Eap_TlsCtx.cachedBufferRecv; } else { @@ -3133,19 +3132,19 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } - sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBuffer); - sizeLeft -= p->Eap_TlsCtx.cachedBufferPntr - p->Eap_TlsCtx.cachedBuffer; + sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); + sizeLeft -= p->Eap_TlsCtx.cachedBufferRecvPntr - p->Eap_TlsCtx.cachedBufferRecv; - Copy(p->Eap_TlsCtx.cachedBufferPntr, dataBuffer, MIN(dataSize, sizeLeft)); + Copy(p->Eap_TlsCtx.cachedBufferRecvPntr, dataBuffer, MIN(dataSize, sizeLeft)); - p->Eap_TlsCtx.cachedBufferPntr += MIN(dataSize, sizeLeft); + p->Eap_TlsCtx.cachedBufferRecvPntr += MIN(dataSize, sizeLeft); } // If we got a cached buffer, we should feed the FIFOs via it - if (p->Eap_TlsCtx.cachedBuffer != NULL) + if (p->Eap_TlsCtx.cachedBufferRecv != NULL) { - dataBuffer = p->Eap_TlsCtx.cachedBuffer; - dataSize = GetMemSize(p->Eap_TlsCtx.cachedBuffer); + dataBuffer = p->Eap_TlsCtx.cachedBufferRecv; + dataSize = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); } // Just acknoweldge that we buffered the fragmented data @@ -3158,17 +3157,18 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } + Debug("Sent EAP-TLS size=%i\n", lcp->DataSize); } else { WriteFifo(p->Eap_TlsCtx.SslPipe->RawIn->SendFifo, dataBuffer, dataSize); SyncSslPipe(p->Eap_TlsCtx.SslPipe); // Delete the cached buffer after we fed it into the pipe - if (p->Eap_TlsCtx.cachedBuffer != NULL) + if (p->Eap_TlsCtx.cachedBufferRecv != NULL) { - Free(p->Eap_TlsCtx.cachedBuffer); - p->Eap_TlsCtx.cachedBuffer = NULL; - p->Eap_TlsCtx.cachedBufferPntr = NULL; + Free(p->Eap_TlsCtx.cachedBufferRecv); + p->Eap_TlsCtx.cachedBufferRecv = NULL; + p->Eap_TlsCtx.cachedBufferRecvPntr = NULL; } if (p->Eap_TlsCtx.SslPipe->IsDisconnected == false) @@ -3177,30 +3177,30 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi // Do we need to send a fragmented packet? if (dataSize > p->Mru1 - 8 - 1 - 1) { - if (p->Eap_TlsCtx.cachedBuffer == NULL) + if (p->Eap_TlsCtx.cachedBufferSend == NULL) { - p->Eap_TlsCtx.cachedBuffer = ZeroMalloc(dataSize); - p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer; + p->Eap_TlsCtx.cachedBufferSend = ZeroMalloc(dataSize); + p->Eap_TlsCtx.cachedBufferSendPntr = p->Eap_TlsCtx.cachedBufferSend; } - p->Eap_TlsCtx.cachedBufferSend = true; - ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, p->Eap_TlsCtx.cachedBuffer, dataSize); + ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, p->Eap_TlsCtx.cachedBufferSend, dataSize); // Now send data from the cached buffer with set fragmentation flag and also total TLS Size tlsLength = dataSize; dataSize = p->Mru1 - 8 - 1 - 1 - 4; // Calculating the maximum payload size (adjusting for including TlsLength) - flags = 1; // L flag - flags |= 1 << 1; // M flag + flags = PPP_EAP_TLS_FLAG_TLS_LENGTH; // L flag + flags |= PPP_EAP_TLS_FLAG_FRAGMENTED; // M flag lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); eap = lcp->Data; - eap->Tls.TlsDataWithLength.TlsLength = tlsLength; - Copy(eap->Tls.TlsDataWithLength.Data, p->Eap_TlsCtx.cachedBuffer, dataSize); - p->Eap_TlsCtx.cachedBufferPntr = p->Eap_TlsCtx.cachedBuffer + dataSize; + eap->Tls.TlsDataWithLength.TlsLength = Endian32(tlsLength); + Copy(eap->Tls.TlsDataWithLength.Data, p->Eap_TlsCtx.cachedBufferSend, dataSize); + p->Eap_TlsCtx.cachedBufferSendPntr += dataSize; if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; return false; } + Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags); } else { @@ -3213,6 +3213,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WHERE; return false; } + Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags); } } } @@ -3243,7 +3244,7 @@ PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UC PPP_LCP* lcp_packet; PPP_EAP* eap_packet; UINT tls_datasize = datasize + sizeof(UCHAR); - if (flags & 1) + if (flags & PPP_EAP_TLS_FLAG_TLS_LENGTH) { tls_datasize += sizeof(UINT32); } @@ -3370,9 +3371,13 @@ void FreePPPSession(PPP_SESSION *p) } // Freeing EAP-TLS context - if (p->Eap_TlsCtx.cachedBuffer != NULL) + if (p->Eap_TlsCtx.cachedBufferRecv != NULL) { - Free(p->Eap_TlsCtx.cachedBuffer); + Free(p->Eap_TlsCtx.cachedBufferRecv); + } + if (p->Eap_TlsCtx.cachedBufferSend != NULL) + { + Free(p->Eap_TlsCtx.cachedBufferRecv); } if (p->Eap_TlsCtx.SslPipe != NULL) { diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index 69174074..ba3ca4ae 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -109,6 +109,12 @@ #define PPP_EAP_TYPE_NAK 3 #define PPP_EAP_TYPE_TLS 13 +// EAP-TLS Flags +#define PPP_EAP_TLS_FLAG_NONE 0 +#define PPP_EAP_TLS_FLAG_TLS_LENGTH 1 << 7 +#define PPP_EAP_TLS_FLAG_FRAGMENTED 1 << 6 +#define PPP_EAP_TLS_FLAG_SSLSTARTED 1 << 5 + // Authentication protocol #define PPP_LCP_AUTH_PAP PPP_PROTOCOL_PAP #define PPP_LCP_AUTH_CHAP PPP_PROTOCOL_CHAP @@ -181,6 +187,11 @@ struct PPP_OPTION UINT AltDataSize; // Alternate data size }; +#ifdef OS_WIN32 +#pragma pack(push, 1) +#endif // OS_WIN32 + + // PPP EAP packet // EAP is a subset of LCP, sharing Code and Id. The Data field is then mapped to this structure // We got 8 bytes of size before this structure @@ -202,16 +213,21 @@ struct PPP_EAP }; } Tls; }; -}; +} GCC_PACKED; + +#ifdef OS_WIN32 +#pragma pack(pop) +#endif // OS_WIN32 struct PPP_EAP_TLS_CONTEXT { SSL_PIPE* SslPipe; DH_CTX* Dh; struct SslClientCertInfo clientCert; - UCHAR* cachedBuffer; - UCHAR* cachedBufferPntr; - bool cachedBufferSend; + UCHAR* cachedBufferRecv; + UCHAR* cachedBufferRecvPntr; + UCHAR* cachedBufferSend; + UCHAR* cachedBufferSendPntr; }; // PPP request resend diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 682214cd..1c24dc30 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5689,7 +5689,7 @@ int SslCertVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) { clientcert->PreverifyErr = X509_STORE_CTX_get_error(ctx); clientcert->PreverifyErrMessage[0] = '\0'; - if (!preverify_ok) + if (!preverify_ok && !clientcert->IgnorePreverifyErr) { const char *msg = X509_verify_cert_error_string(clientcert->PreverifyErr); StrCpy(clientcert->PreverifyErrMessage, PREVERIFY_ERR_MESSAGE_SIZE, (char *)msg); diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 1744ff70..0b8f68a5 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -1135,7 +1135,7 @@ UINT SecureRecv(SOCK *sock, void *data, UINT size); bool StartSSL(SOCK *sock, X *x, K *priv); bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname); bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x); -void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx); +void AddChainSslCertOnDirectory(struct ssl_st *ctx); bool SendAll(SOCK *sock, void *data, UINT size, bool secure); void SendAdd(SOCK *sock, void *data, UINT size); bool SendNow(SOCK *sock, int secure); @@ -1403,6 +1403,7 @@ void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout); #define PREVERIFY_ERR_MESSAGE_SIZE 100 // Info on client certificate collected during TLS handshake struct SslClientCertInfo { + bool IgnorePreverifyErr; int PreverifyErr; char PreverifyErrMessage[PREVERIFY_ERR_MESSAGE_SIZE]; X *X; From a2b7cb0148e51819340a3c0276c5cefa3c912db0 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 14:40:46 +0300 Subject: [PATCH 06/13] Added possibility to load CA certificates from chain_certs folder to allow verifying the client certificates against it. --- src/Cedar/Proto_PPP.c | 9 ++++----- src/Mayaqua/Network.c | 12 ++++++++++-- src/Mayaqua/Network.h | 1 - 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 50503ae3..3c01613b 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -251,7 +251,7 @@ void PPPThread(THREAD *thread, void *param) { PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; - return false; + break; } break; case PPP_EAP_TYPE_IDENTITY: @@ -265,7 +265,7 @@ void PPPThread(THREAD *thread, void *param) { PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; - return false; + break; } break; } @@ -407,7 +407,7 @@ void PPPThread(THREAD *thread, void *param) } else { - WaitForTubes(tubes, 1, 1000); // Increasing timeout to make the ticks a bit slower + WaitForTubes(tubes, 1, 300); // Increasing timeout to make the ticks a bit slower } if (IsTubeConnected(p->TubeRecv) == false || IsTubeConnected(p->TubeSend) == false) @@ -3053,7 +3053,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "", &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, - p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL, + p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, p->Eap_TlsCtx.clientCert.X, IPC_LAYER_3); if (ipc != NULL) @@ -3112,7 +3112,6 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi // First we initialize the SslPipe if it is not already inited if (p->Eap_TlsCtx.SslPipe == NULL) { - p->Eap_TlsCtx.clientCert.IgnorePreverifyErr = true; p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT); p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.clientCert)); } diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 1c24dc30..22991125 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5689,7 +5689,7 @@ int SslCertVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) { clientcert->PreverifyErr = X509_STORE_CTX_get_error(ctx); clientcert->PreverifyErrMessage[0] = '\0'; - if (!preverify_ok && !clientcert->IgnorePreverifyErr) + if (!preverify_ok) { const char *msg = X509_verify_cert_error_string(clientcert->PreverifyErr); StrCpy(clientcert->PreverifyErrMessage, PREVERIFY_ERR_MESSAGE_SIZE, (char *)msg); @@ -11785,7 +11785,15 @@ bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x) if (x_copy != NULL) { - SSL_CTX_add_extra_chain_cert(ctx, x_copy->x509); + if (x_copy->root_cert) + { + X509_STORE* store = SSL_CTX_get_cert_store(ctx); + X509_STORE_add_cert(store, x->x509); + } + else + { + SSL_CTX_add_extra_chain_cert(ctx, x_copy->x509); + } x_copy->do_not_free = true; ret = true; diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 0b8f68a5..2019da20 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -1403,7 +1403,6 @@ void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout); #define PREVERIFY_ERR_MESSAGE_SIZE 100 // Info on client certificate collected during TLS handshake struct SslClientCertInfo { - bool IgnorePreverifyErr; int PreverifyErr; char PreverifyErrMessage[PREVERIFY_ERR_MESSAGE_SIZE]; X *X; From 723f38e72f09642b63738eb0439a3a85e7e5ef7d Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 19:15:30 +0300 Subject: [PATCH 07/13] Fixing Linux... --- src/Cedar/Proto_PPP.c | 69 +++++++++++++++++++++++++++++++++++-------- src/Mayaqua/Network.c | 1 + 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 3c01613b..2cd9cb27 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -1186,8 +1186,21 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req } else { - // Means we got a Success or Failure packet... - Debug("We got a CODE %i from client with zero size EAP structure, that shouldn't be happening!\n", pp->Lcp->Code); + PPP_EAP* eap; + + Debug("We got a CODE=%i ID=%i from client with zero size EAP structure, that shouldn't be happening!\n", pp->Lcp->Code, pp->Lcp->Id); + + eap = req->Lcp->Data; + if (eap->Type == PPP_EAP_TYPE_TLS) + { + PPP_LCP* lcp = BuildEAPTlsRequest(p->Eap_PacketId++, 0, PPP_EAP_TLS_FLAG_NONE); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } } return false; } @@ -2996,6 +3009,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi UCHAR* dataBuffer; UINT dataSize; UINT tlsLength = 0; + UINT i; bool isFragmented = false; PPP_LCP* lcp; PPP_EAP* eap; @@ -3058,31 +3072,44 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi if (ipc != NULL) { + PPP_PACKET* pack; + p->Ipc = ipc; PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS); // Just send an EAP-Success + pack = ZeroMalloc(sizeof(PPP_PACKET)); + pack->IsControl = true; + pack->Protocol = PPP_PROTOCOL_EAP; lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, p->Eap_PacketId++); - if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + pack->Lcp = lcp; + Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize); + if (!PPPSendPacketAndFree(p, pack)) { PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; return false; } - Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize); return true; } else { + PPP_PACKET* pack; + PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); + + pack = ZeroMalloc(sizeof(PPP_PACKET)); + pack->IsControl = true; + pack->Protocol = PPP_PROTOCOL_EAP; lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId++); - if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + pack->Lcp = lcp; + Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize); + if (!PPPSendPacketAndFree(p, pack)) { PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; return false; } - Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize); return false; } } @@ -3102,6 +3129,13 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi dataSize -= 4; tlsLength = Endian32(eap_packet->Tls.TlsDataWithLength.TlsLength); } + /*Debug("=======RECV EAP-TLS PACKET DUMP=======\n"); + for (i = 0; i < dataSize; i++) + { + if (i > 0) printf(" "); + Debug("%02X", dataBuffer[i]); + } + Debug("\n=======RECV EAP-TLS PACKET DUMP END=======\n");*/ if (eap_packet->Tls.Flags & PPP_EAP_TLS_FLAG_FRAGMENTED) { isFragmented = true; @@ -3124,19 +3158,17 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi p->Eap_TlsCtx.cachedBufferRecv = ZeroMalloc(MAX(dataSize, tlsLength)); p->Eap_TlsCtx.cachedBufferRecvPntr = p->Eap_TlsCtx.cachedBufferRecv; } - else + else if (p->Eap_TlsCtx.cachedBufferRecv == NULL) { - Debug("We didn't get the tlsLength size! We're probably corrupt.\n"); - PPPSetStatus(p, PPP_STATUS_FAIL); - WHERE; - return false; + p->Eap_TlsCtx.cachedBufferRecv = ZeroMalloc(MAX(dataSize, PPP_MRU_MAX * 10)); // 10 MRUs should be enough + p->Eap_TlsCtx.cachedBufferRecvPntr = p->Eap_TlsCtx.cachedBufferRecv; } sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); sizeLeft -= p->Eap_TlsCtx.cachedBufferRecvPntr - p->Eap_TlsCtx.cachedBufferRecv; - Copy(p->Eap_TlsCtx.cachedBufferRecvPntr, dataBuffer, MIN(dataSize, sizeLeft)); + Copy(p->Eap_TlsCtx.cachedBufferRecvPntr, dataBuffer, MIN(sizeLeft, dataSize)); - p->Eap_TlsCtx.cachedBufferRecvPntr += MIN(dataSize, sizeLeft); + p->Eap_TlsCtx.cachedBufferRecvPntr += MIN(sizeLeft, dataSize); } // If we got a cached buffer, we should feed the FIFOs via it @@ -3144,6 +3176,10 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi { dataBuffer = p->Eap_TlsCtx.cachedBufferRecv; dataSize = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); + if (dataSize == MAX_BUFFERING_PACKET_SIZE) + { + dataSize = p->Eap_TlsCtx.cachedBufferRecvPntr - p->Eap_TlsCtx.cachedBufferRecv; + } } // Just acknoweldge that we buffered the fragmented data @@ -3160,6 +3196,13 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi } else { + /*Debug("=======RECV EAP-TLS FIFO DUMP=======\n"); + for (i = 0; i < dataSize; i++) + { + if (i > 0) printf(" "); + Debug("%02X", dataBuffer[i]); + } + Debug("\n=======RECV EAP-TLS PACKET FIFO END=======\n");*/ WriteFifo(p->Eap_TlsCtx.SslPipe->RawIn->SendFifo, dataBuffer, dataSize); SyncSslPipe(p->Eap_TlsCtx.SslPipe); // Delete the cached buffer after we fed it into the pipe diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 22991125..39ef7f3e 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5731,6 +5731,7 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee { SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method()); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); // For some reason pppd under linux doesn't like it AddChainSslCertOnDirectory(ssl_ctx); From 39becfe4abb2186fec523e6242de6c8bf2542a55 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 17:50:07 +0300 Subject: [PATCH 08/13] Some hacks to make Android VPN Client Pro working --- src/Cedar/Proto_PPP.c | 36 ++++++++++++++++++++++++++++++++---- src/Mayaqua/Network.c | 3 +++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 2cd9cb27..6734239a 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -3063,6 +3063,22 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi ETHERIP_ID d; UINT error_code; + /*if (!p->Eap_TlsCtx.SslPipe->IsDisconnected) + { + dataSize = FifoSize(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo); + lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, 0); + eap = lcp->Data; + ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, &(eap->Tls.TlsDataWithoutLength), dataSize); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags); + return true; + }*/ + PPPParseUsername(p->Cedar, p->Eap_Identity, &d); ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "", @@ -3073,6 +3089,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi if (ipc != NULL) { PPP_PACKET* pack; + UINT identificator = p->Eap_PacketId - 1; // THIS IS A HACK TO SUPPORT VPN Client Pro on Android!!! p->Ipc = ipc; PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS); @@ -3081,7 +3098,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi pack = ZeroMalloc(sizeof(PPP_PACKET)); pack->IsControl = true; pack->Protocol = PPP_PROTOCOL_EAP; - lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, p->Eap_PacketId++); + lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, identificator); pack->Lcp = lcp; Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize); if (!PPPSendPacketAndFree(p, pack)) @@ -3095,13 +3112,14 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi else { PPP_PACKET* pack; + UINT identificator = p->Eap_PacketId - 1; // THIS IS A HACK TO SUPPORT VPN Client Pro on Android!!! PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); pack = ZeroMalloc(sizeof(PPP_PACKET)); pack->IsControl = true; pack->Protocol = PPP_PROTOCOL_EAP; - lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId++); + lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, identificator); pack->Lcp = lcp; Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize); if (!PPPSendPacketAndFree(p, pack)) @@ -3115,8 +3133,18 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi } else { - Debug("Weird ACK for no reason at all...\n"); - return false; + // Some clients needs a little help it seems - namely VPN Client Pro on Android + flags |= PPP_EAP_TLS_FLAG_SSLSTARTED; + lcp = BuildEAPTlsRequest(p->Eap_PacketId++, 0, flags); + PPPSetStatus(p, PPP_STATUS_AUTHENTICATING); + if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + Debug("Sent EAP-TLS size=%i\n", lcp->DataSize); + return true; } } return true; diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 39ef7f3e..6b621759 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5731,7 +5731,10 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee { SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method()); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); + +#ifdef SSL_OP_NO_SSLv3 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); // For some reason pppd under linux doesn't like it +#endif AddChainSslCertOnDirectory(ssl_ctx); From 9180e065a00586441b0e59a09d9f2d7b4a94774a Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 20:29:31 +0300 Subject: [PATCH 09/13] Some weirdness fixes --- src/Mayaqua/Network.c | 2 +- src/Mayaqua/Network.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 6b621759..b79238f7 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5732,7 +5732,7 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method()); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); -#ifdef SSL_OP_NO_SSLv3 +#ifdef SSL_OP_NO_TLSv1_3 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); // For some reason pppd under linux doesn't like it #endif diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 2019da20..1744ff70 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -1135,7 +1135,7 @@ UINT SecureRecv(SOCK *sock, void *data, UINT size); bool StartSSL(SOCK *sock, X *x, K *priv); bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname); bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x); -void AddChainSslCertOnDirectory(struct ssl_st *ctx); +void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx); bool SendAll(SOCK *sock, void *data, UINT size, bool secure); void SendAdd(SOCK *sock, void *data, UINT size); bool SendNow(SOCK *sock, int secure); From 8a856e46726eda117464f3915a3e82c29e4797e9 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sat, 2 May 2020 21:05:42 +0300 Subject: [PATCH 10/13] Codestyle fixes --- src/Cedar/IPC.c | 2 +- src/Cedar/Proto_PPP.c | 212 ++++++++++++++++++++--------------------- src/Cedar/Proto_PPP.h | 96 +++++++++---------- src/Cedar/Proto_SSTP.c | 2 +- src/Cedar/Proto_SSTP.h | 2 +- 5 files changed, 157 insertions(+), 157 deletions(-) diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index ffa9baaa..96de8962 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -948,7 +948,7 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt) { IPV4_HEADER ip; - UDP_HEADER* udp; + UDP_HEADER *udp; DHCPV4_HEADER dhcp; UINT blank_size = 128 + 64; BUF *ret; diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 6734239a..846e8984 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -147,7 +147,7 @@ void PPPThread(THREAD *thread, void *param) // Process responses if (!receivedPacketProcessed && p->CurrentPacket != NULL && p->CurrentPacket->IsControl && PPP_CODE_IS_RESPONSE(p->CurrentPacket->Protocol, p->CurrentPacket->Lcp->Code) && !PPP_STATUS_IS_UNAVAILABLE(p->PPPStatus)) { - PPP_PACKET* request = NULL; + PPP_PACKET *request = NULL; // Removing from resend list for (i = 0; i < LIST_NUM(p->SentReqPacketList); i++) { @@ -233,9 +233,9 @@ void PPPThread(THREAD *thread, void *param) } else if (p->PPPStatus == PPP_STATUS_BEFORE_AUTH && p->AuthProtocol == PPP_PROTOCOL_EAP) { - PPP_LCP* lcpEap; - PPP_EAP* eapPacket; - UCHAR* welcomeMessage = "Welcome to the SoftEther VPN server!"; + PPP_LCP *lcpEap; + PPP_EAP *eapPacket; + UCHAR *welcomeMessage = "Welcome to the SoftEther VPN server!"; UCHAR flags = PPP_EAP_TLS_FLAG_NONE; // We got to start EAP when we got no LCP packets from the client on previous iteration // which means we parsed all the client requests and responses @@ -775,7 +775,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req // probably means the PPP client is not compatible anyway so we fail the connection if (p->PPPStatus != PPP_STATUS_NETWORK_LAYER) { - USHORT* protocol = pp->Lcp->Data; + USHORT *protocol = pp->Lcp->Data; Debug("Protocol 0x%x rejected before auth, probably unsupported client, failing connection\n", *protocol); PPPSetStatus(p, PPP_STATUS_FAIL); WHERE; @@ -783,7 +783,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req } else { - USHORT* protocol = pp->Lcp->Data; + USHORT *protocol = pp->Lcp->Data; if (*protocol == PPP_PROTOCOL_IPCP || *protocol == PPP_PROTOCOL_IP) { p->IPv4_State = PPP_PROTO_STATUS_REJECTED; @@ -830,7 +830,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req } else { - PPP_LCP* lcp = NewPPPLCP(PPP_LCP_CODE_REQ, 0); + PPP_LCP *lcp = NewPPPLCP(PPP_LCP_CODE_REQ, 0); Add(lcp->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &value, sizeof(USHORT))); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_LCP, lcp)) { @@ -870,7 +870,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req if (!isAccepted) { UINT64 offer = 0; - PPP_LCP* c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); + PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); UCHAR ms_chap_v2_code[3]; WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); @@ -952,7 +952,7 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req // Process CHAP responses bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req) { - PPP_LCP* lcp; + PPP_LCP *lcp; if (pp->Lcp->Code == PPP_CHAP_CODE_RESPONSE) { bool ok = false; @@ -989,8 +989,8 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re { char hex[MAX_SIZE]; char ret_str[MAX_SIZE]; - BUF* lcp_ret_data = NewBuf(); - PPP_PACKET* res = ZeroMalloc(sizeof(PPP_PACKET)); + BUF *lcp_ret_data = NewBuf(); + PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET)); BinToStr(hex, sizeof(hex), p->MsChapV2_ServerResponse, 20); Format(ret_str, sizeof(ret_str), @@ -1026,8 +1026,8 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re { char hex[MAX_SIZE]; char ret_str[MAX_SIZE]; - BUF* lcp_ret_data = NewBuf(); - PPP_PACKET* res = ZeroMalloc(sizeof(PPP_PACKET)); + BUF *lcp_ret_data = NewBuf(); + PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET)); BinToStr(hex, sizeof(hex), p->MsChapV2_ServerChallenge, 16); @@ -1076,7 +1076,7 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re IP prevAddrStruct; char prevAddrStr[MAX_SIZE]; UINT prevAddr; - PPP_LCP* c; + PPP_LCP *c; UINT ui; if (!PPPGetIPAddressValueFromLCP(pp->Lcp, PPP_IPCP_OPTION_IP, &addrStruct) || pp->Lcp->Code == PPP_LCP_CODE_REJECT || pp->Lcp->Code == PPP_LCP_CODE_CODE_REJECT) @@ -1134,14 +1134,14 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re } // Process EAP responses -bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req) +bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req) { if (pp->Lcp->DataSize >= 1) { - PPP_EAP* eap_packet = pp->Lcp->Data; + PPP_EAP *eap_packet = pp->Lcp->Data; UINT eap_datasize = pp->Lcp->DataSize - 1; UINT64 offer = 0; - PPP_LCP* c; + PPP_LCP *c; UCHAR ms_chap_v2_code[3]; WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); @@ -1186,14 +1186,14 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req } else { - PPP_EAP* eap; + PPP_EAP *eap; Debug("We got a CODE=%i ID=%i from client with zero size EAP structure, that shouldn't be happening!\n", pp->Lcp->Code, pp->Lcp->Id); eap = req->Lcp->Data; if (eap->Type == PPP_EAP_TYPE_TLS) { - PPP_LCP* lcp = BuildEAPTlsRequest(p->Eap_PacketId++, 0, PPP_EAP_TLS_FLAG_NONE); + PPP_LCP *lcp = BuildEAPTlsRequest(p->Eap_PacketId++, 0, PPP_EAP_TLS_FLAG_NONE); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { PPPSetStatus(p, PPP_STATUS_FAIL); @@ -1356,12 +1356,12 @@ bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) return true; } -bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) +bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) { if (p->PPPStatus != PPP_STATUS_BEFORE_AUTH && !p->AuthOk) { - PPP_LCP* lcp = NewPPPLCP(PPP_PAP_CODE_NAK, pp->Lcp->Id); - PPP_PACKET* ret = ZeroMalloc(sizeof(PPP_PACKET)); + PPP_LCP *lcp = NewPPPLCP(PPP_PAP_CODE_NAK, pp->Lcp->Id); + PPP_PACKET *ret = ZeroMalloc(sizeof(PPP_PACKET)); Debug("Got a PAP request before we're ready for AUTH procedure!\n"); @@ -1489,8 +1489,8 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) } if (p->AuthOk) { - PPP_LCP* lcp = NewPPPLCP(PPP_PAP_CODE_ACK, pp->Lcp->Id); - PPP_PACKET* ret = ZeroMalloc(sizeof(PPP_PACKET)); + PPP_LCP *lcp = NewPPPLCP(PPP_PAP_CODE_ACK, pp->Lcp->Id); + PPP_PACKET *ret = ZeroMalloc(sizeof(PPP_PACKET)); ret->IsControl = true; ret->Protocol = PPP_PROTOCOL_PAP; ret->Lcp = lcp; @@ -1509,8 +1509,8 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) } if (!p->AuthOk) { - PPP_LCP* lcp = NewPPPLCP(PPP_PAP_CODE_NAK, pp->Lcp->Id); - PPP_PACKET* ret = ZeroMalloc(sizeof(PPP_PACKET)); + PPP_LCP *lcp = NewPPPLCP(PPP_PAP_CODE_NAK, pp->Lcp->Id); + PPP_PACKET *ret = ZeroMalloc(sizeof(PPP_PACKET)); ret->IsControl = true; ret->Protocol = PPP_PROTOCOL_PAP; ret->Lcp = lcp; @@ -1533,7 +1533,7 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) } -bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) +bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) { PPP_IPOPTION o; PPP_IPOPTION res; @@ -1547,7 +1547,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) bool ok = true; bool processed = false; bool isEmptyIpAddress = false; - PPP_LCP* c; + PPP_LCP *c; if (p->IPv4_State == PPP_PROTO_STATUS_REJECTED) { @@ -1825,7 +1825,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) // it is kind of dirty but fixes issues on some clients (namely VPN Client Pro on Android) if (p->IPv4_State == PPP_PROTO_STATUS_CLOSED && p->ClientAddressOption.ServerAddress != 0 && ok) { - PPP_LCP* c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); + PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0); UINT ui = p->ClientAddressOption.ServerAddress; Add(c->OptionList, NewPPPOption(PPP_IPCP_OPTION_IP, &ui, sizeof(UINT))); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_IPCP, c)) @@ -1865,22 +1865,22 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET* pp) } // Process EAP request packets -bool PPPProcessEAPRequestPacket(PPP_SESSION* p, PPP_PACKET* pp) +bool PPPProcessEAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) { Debug("We got an EAP request, which is weird...\n"); return false; } // LCP option based packets utility -bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET* pp) +bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET *pp) { return PPPRejectLCPOptionsEx(p, pp, false); } -bool PPPRejectLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate) +bool PPPRejectLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate) { UINT i = 0; bool toBeRejected = false; - PPP_PACKET* ret; + PPP_PACKET *ret; for (i = 0; i < LIST_NUM(pp->Lcp->OptionList); i++) { PPP_OPTION *t = LIST_DATA(pp->Lcp->OptionList, i); @@ -1924,14 +1924,14 @@ bool PPPRejectLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate) PPPSendPacketAndFree(p, ret); return true; } -bool PPPNackLCPOptions(PPP_SESSION *p, PPP_PACKET* pp) +bool PPPNackLCPOptions(PPP_SESSION *p, PPP_PACKET *pp) { return PPPNackLCPOptionsEx(p, pp, false); } -bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate) +bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate) { UINT i = 0; - PPP_PACKET* ret; + PPP_PACKET *ret; bool toBeNACKed = false; for (i = 0; i < LIST_NUM(pp->Lcp->OptionList); i++) { @@ -1977,14 +1977,14 @@ bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate) PPPSendPacketAndFree(p, ret); return true; } -bool PPPAckLCPOptions(PPP_SESSION *p, PPP_PACKET* pp) +bool PPPAckLCPOptions(PPP_SESSION *p, PPP_PACKET *pp) { return PPPAckLCPOptionsEx(p, pp, false); } -bool PPPAckLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate) +bool PPPAckLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate) { UINT i = 0; - PPP_PACKET* ret; + PPP_PACKET *ret; bool toBeACKed = false; if (LIST_NUM(pp->Lcp->OptionList) == 0) { @@ -2042,7 +2042,7 @@ bool PPPSendAndRetransmitRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c) { PPP_PACKET *pp; UINT64 now = Tick64(); - PPP_REQUEST_RESEND* resend; + PPP_REQUEST_RESEND *resend; // Validate arguments if (p == NULL || c == NULL) @@ -2156,7 +2156,7 @@ LABEL_LOOP: PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p) { - PPP_PACKET* ret = NULL; + PPP_PACKET *ret = NULL; UINT i = 0; if (p->CurrentPacket != NULL) { @@ -2165,7 +2165,7 @@ PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p) } for (i = 0; i < LIST_NUM(p->DelayedPackets); i++) { - PPP_DELAYED_PACKET* t = LIST_DATA(p->DelayedPackets, i); + PPP_DELAYED_PACKET *t = LIST_DATA(p->DelayedPackets, i); if (t->DelayTicks > 0) { t->DelayTicks--; @@ -2189,10 +2189,10 @@ PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p) if (ret != NULL && ret->IsControl && ret->Lcp != NULL) { - PPP_DELAYED_PACKET* firstRelated = NULL; + PPP_DELAYED_PACKET *firstRelated = NULL; for (i = 0; i < LIST_NUM(p->DelayedPackets); i++) { - PPP_DELAYED_PACKET* t = LIST_DATA(p->DelayedPackets, i); + PPP_DELAYED_PACKET *t = LIST_DATA(p->DelayedPackets, i); char related = PPPRelatedPacketComparator(ret, t->Packet); if (related != 0xF && related != 0xE) { @@ -2240,7 +2240,7 @@ PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p) void PPPAddNextPacket(PPP_SESSION *p, PPP_PACKET *pp, UINT delay) { - PPP_DELAYED_PACKET* t = ZeroMalloc(sizeof(PPP_DELAYED_PACKET)); + PPP_DELAYED_PACKET *t = ZeroMalloc(sizeof(PPP_DELAYED_PACKET)); UINT i; if (p->CurrentPacket == pp) { @@ -2262,10 +2262,10 @@ void PPPAddNextPacket(PPP_SESSION *p, PPP_PACKET *pp, UINT delay) Debug("after sorting delayeds end\n");*/ } -int PPPDelayedPacketsComparator(const void* a, const void* b) +int PPPDelayedPacketsComparator(const void *a, const void *b) { - PPP_DELAYED_PACKET* first = a; - PPP_DELAYED_PACKET* second = b; + PPP_DELAYED_PACKET *first = a; + PPP_DELAYED_PACKET *second = b; char related = PPPRelatedPacketComparator(first->Packet, second->Packet); @@ -2305,7 +2305,7 @@ int PPPDelayedPacketsComparator(const void* a, const void* b) // 1 - packet a comes after packet b // 0xF - packet is not related // 0xE - we got an error while comparing, treating as not related would be the most correct -char PPPRelatedPacketComparator(PPP_PACKET* a, PPP_PACKET* b) +char PPPRelatedPacketComparator(PPP_PACKET *a, PPP_PACKET *b) { if (a->IsControl && b->IsControl && a->Lcp != NULL && b->Lcp != NULL && @@ -2570,7 +2570,7 @@ LABEL_ERROR: } // Analyse MS CHAP v2 Response packet -bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION* p, PPP_PACKET* pp) +bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp) { bool ok = false; @@ -2813,7 +2813,7 @@ BUF *BuildLCPData(PPP_LCP *c) } // Build the MS CHAP v2 challenge packet -PPP_LCP *BuildMSCHAP2ChallengePacket(PPP_SESSION* p) +PPP_LCP *BuildMSCHAP2ChallengePacket(PPP_SESSION *p) { PPP_LCP *lcp; BUF *b; @@ -3004,27 +3004,27 @@ bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip) } // EAP packet utilities -bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSize) +bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSize) { - UCHAR* dataBuffer; + UCHAR *dataBuffer; UINT dataSize; UINT tlsLength = 0; UINT i; bool isFragmented = false; - PPP_LCP* lcp; - PPP_EAP* eap; + PPP_LCP *lcp; + PPP_EAP *eap; UCHAR flags; UINT64 sizeLeft = 0; Debug("Got EAP-TLS size=%i\n", eapTlsSize); if (eapTlsSize == 1) { // This is an EAP-TLS message ACK - if (p->Eap_TlsCtx.cachedBufferSend != NULL) + if (p->Eap_TlsCtx.CachedBufferSend != NULL) { // We got an ACK to transmit the next fragmented message dataSize = p->Mru1 - 8 - 1 - 1; // Calculating the maximum payload size (without TlsLength) - sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBufferSend); - sizeLeft -= p->Eap_TlsCtx.cachedBufferSendPntr - p->Eap_TlsCtx.cachedBufferSend; + sizeLeft = GetMemSize(p->Eap_TlsCtx.CachedBufferSend); + sizeLeft -= p->Eap_TlsCtx.CachedBufferSendPntr - p->Eap_TlsCtx.CachedBufferSend; flags = PPP_EAP_TLS_FLAG_FRAGMENTED; // M flag if (dataSize > sizeLeft) @@ -3034,8 +3034,8 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi } lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); eap = lcp->Data; - Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.cachedBufferSendPntr, dataSize); - p->Eap_TlsCtx.cachedBufferSendPntr += dataSize; + Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.CachedBufferSendPntr, dataSize); + p->Eap_TlsCtx.CachedBufferSendPntr += dataSize; if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { @@ -3048,18 +3048,18 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi if (flags == PPP_EAP_TLS_FLAG_NONE) { // As it is the latest message, we need to cleanup - Free(p->Eap_TlsCtx.cachedBufferSend); - p->Eap_TlsCtx.cachedBufferSend = NULL; - p->Eap_TlsCtx.cachedBufferSendPntr = NULL; + Free(p->Eap_TlsCtx.CachedBufferSend); + p->Eap_TlsCtx.CachedBufferSend = NULL; + p->Eap_TlsCtx.CachedBufferSendPntr = NULL; } } else { // It probably should be the final ACK on closed SSL pipe SyncSslPipe(p->Eap_TlsCtx.SslPipe); - if (p->Eap_TlsCtx.clientCert.X != NULL) + if (p->Eap_TlsCtx.ClientCert.X != NULL) { - IPC* ipc; + IPC *ipc; ETHERIP_ID d; UINT error_code; @@ -3083,12 +3083,12 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "", &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, - p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, p->Eap_TlsCtx.clientCert.X, + p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, p->Eap_TlsCtx.ClientCert.X, IPC_LAYER_3); if (ipc != NULL) { - PPP_PACKET* pack; + PPP_PACKET *pack; UINT identificator = p->Eap_PacketId - 1; // THIS IS A HACK TO SUPPORT VPN Client Pro on Android!!! p->Ipc = ipc; @@ -3111,7 +3111,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi } else { - PPP_PACKET* pack; + PPP_PACKET *pack; UINT identificator = p->Eap_PacketId - 1; // THIS IS A HACK TO SUPPORT VPN Client Pro on Android!!! PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); @@ -3175,45 +3175,45 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi if (p->Eap_TlsCtx.SslPipe == NULL) { p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT); - p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.clientCert)); + p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.ClientCert)); } // If the current frame is fragmented, or it is a possible last of a fragmented series, bufferize it - if (isFragmented || p->Eap_TlsCtx.cachedBufferRecv != NULL) + if (isFragmented || p->Eap_TlsCtx.CachedBufferRecv != NULL) { - if (p->Eap_TlsCtx.cachedBufferRecv == NULL && tlsLength > 0) + if (p->Eap_TlsCtx.CachedBufferRecv == NULL && tlsLength > 0) { - p->Eap_TlsCtx.cachedBufferRecv = ZeroMalloc(MAX(dataSize, tlsLength)); - p->Eap_TlsCtx.cachedBufferRecvPntr = p->Eap_TlsCtx.cachedBufferRecv; + p->Eap_TlsCtx.CachedBufferRecv = ZeroMalloc(MAX(dataSize, tlsLength)); + p->Eap_TlsCtx.CachedBufferRecvPntr = p->Eap_TlsCtx.CachedBufferRecv; } - else if (p->Eap_TlsCtx.cachedBufferRecv == NULL) + else if (p->Eap_TlsCtx.CachedBufferRecv == NULL) { - p->Eap_TlsCtx.cachedBufferRecv = ZeroMalloc(MAX(dataSize, PPP_MRU_MAX * 10)); // 10 MRUs should be enough - p->Eap_TlsCtx.cachedBufferRecvPntr = p->Eap_TlsCtx.cachedBufferRecv; + p->Eap_TlsCtx.CachedBufferRecv = ZeroMalloc(MAX(dataSize, PPP_MRU_MAX * 10)); // 10 MRUs should be enough + p->Eap_TlsCtx.CachedBufferRecvPntr = p->Eap_TlsCtx.CachedBufferRecv; } - sizeLeft = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); - sizeLeft -= p->Eap_TlsCtx.cachedBufferRecvPntr - p->Eap_TlsCtx.cachedBufferRecv; + sizeLeft = GetMemSize(p->Eap_TlsCtx.CachedBufferRecv); + sizeLeft -= p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv; - Copy(p->Eap_TlsCtx.cachedBufferRecvPntr, dataBuffer, MIN(sizeLeft, dataSize)); + Copy(p->Eap_TlsCtx.CachedBufferRecvPntr, dataBuffer, MIN(sizeLeft, dataSize)); - p->Eap_TlsCtx.cachedBufferRecvPntr += MIN(sizeLeft, dataSize); + p->Eap_TlsCtx.CachedBufferRecvPntr += MIN(sizeLeft, dataSize); } // If we got a cached buffer, we should feed the FIFOs via it - if (p->Eap_TlsCtx.cachedBufferRecv != NULL) + if (p->Eap_TlsCtx.CachedBufferRecv != NULL) { - dataBuffer = p->Eap_TlsCtx.cachedBufferRecv; - dataSize = GetMemSize(p->Eap_TlsCtx.cachedBufferRecv); + dataBuffer = p->Eap_TlsCtx.CachedBufferRecv; + dataSize = GetMemSize(p->Eap_TlsCtx.CachedBufferRecv); if (dataSize == MAX_BUFFERING_PACKET_SIZE) { - dataSize = p->Eap_TlsCtx.cachedBufferRecvPntr - p->Eap_TlsCtx.cachedBufferRecv; + dataSize = p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv; } } // Just acknoweldge that we buffered the fragmented data if (isFragmented) { - PPP_LCP* lcp = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId++, PPP_EAP_TYPE_TLS, 0); + PPP_LCP *lcp = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId++, PPP_EAP_TYPE_TLS, 0); if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { PPPSetStatus(p, PPP_STATUS_FAIL); @@ -3234,11 +3234,11 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi WriteFifo(p->Eap_TlsCtx.SslPipe->RawIn->SendFifo, dataBuffer, dataSize); SyncSslPipe(p->Eap_TlsCtx.SslPipe); // Delete the cached buffer after we fed it into the pipe - if (p->Eap_TlsCtx.cachedBufferRecv != NULL) + if (p->Eap_TlsCtx.CachedBufferRecv != NULL) { - Free(p->Eap_TlsCtx.cachedBufferRecv); - p->Eap_TlsCtx.cachedBufferRecv = NULL; - p->Eap_TlsCtx.cachedBufferRecvPntr = NULL; + Free(p->Eap_TlsCtx.CachedBufferRecv); + p->Eap_TlsCtx.CachedBufferRecv = NULL; + p->Eap_TlsCtx.CachedBufferRecvPntr = NULL; } if (p->Eap_TlsCtx.SslPipe->IsDisconnected == false) @@ -3247,12 +3247,12 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi // Do we need to send a fragmented packet? if (dataSize > p->Mru1 - 8 - 1 - 1) { - if (p->Eap_TlsCtx.cachedBufferSend == NULL) + if (p->Eap_TlsCtx.CachedBufferSend == NULL) { - p->Eap_TlsCtx.cachedBufferSend = ZeroMalloc(dataSize); - p->Eap_TlsCtx.cachedBufferSendPntr = p->Eap_TlsCtx.cachedBufferSend; + p->Eap_TlsCtx.CachedBufferSend = ZeroMalloc(dataSize); + p->Eap_TlsCtx.CachedBufferSendPntr = p->Eap_TlsCtx.CachedBufferSend; } - ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, p->Eap_TlsCtx.cachedBufferSend, dataSize); + ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, p->Eap_TlsCtx.CachedBufferSend, dataSize); // Now send data from the cached buffer with set fragmentation flag and also total TLS Size tlsLength = dataSize; @@ -3262,8 +3262,8 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags); eap = lcp->Data; eap->Tls.TlsDataWithLength.TlsLength = Endian32(tlsLength); - Copy(eap->Tls.TlsDataWithLength.Data, p->Eap_TlsCtx.cachedBufferSend, dataSize); - p->Eap_TlsCtx.cachedBufferSendPntr += dataSize; + Copy(eap->Tls.TlsDataWithLength.Data, p->Eap_TlsCtx.CachedBufferSend, dataSize); + p->Eap_TlsCtx.CachedBufferSendPntr += dataSize; if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp)) { PPPSetStatus(p, PPP_STATUS_FAIL); @@ -3297,8 +3297,8 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSi PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize) { - PPP_EAP* eap_packet; - PPP_LCP* lcp_packet; + PPP_EAP *eap_packet; + PPP_LCP *lcp_packet; UINT lcpDatasize; lcpDatasize = datasize + sizeof(UCHAR); eap_packet = ZeroMalloc(lcpDatasize); @@ -3311,8 +3311,8 @@ PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize) PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UCHAR flags) { - PPP_LCP* lcp_packet; - PPP_EAP* eap_packet; + PPP_LCP *lcp_packet; + PPP_EAP *eap_packet; UINT tls_datasize = datasize + sizeof(UCHAR); if (flags & PPP_EAP_TLS_FLAG_TLS_LENGTH) { @@ -3324,7 +3324,7 @@ PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UC return lcp_packet; } -PPP_LCP* BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags) +PPP_LCP *BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags) { return BuildEAPTlsPacketEx(PPP_EAP_CODE_REQUEST, id, PPP_EAP_TYPE_TLS, datasize, flags); } @@ -3441,21 +3441,21 @@ void FreePPPSession(PPP_SESSION *p) } // Freeing EAP-TLS context - if (p->Eap_TlsCtx.cachedBufferRecv != NULL) + if (p->Eap_TlsCtx.CachedBufferRecv != NULL) { - Free(p->Eap_TlsCtx.cachedBufferRecv); + Free(p->Eap_TlsCtx.CachedBufferRecv); } - if (p->Eap_TlsCtx.cachedBufferSend != NULL) + if (p->Eap_TlsCtx.CachedBufferSend != NULL) { - Free(p->Eap_TlsCtx.cachedBufferRecv); + Free(p->Eap_TlsCtx.CachedBufferRecv); } if (p->Eap_TlsCtx.SslPipe != NULL) { FreeSslPipe(p->Eap_TlsCtx.SslPipe); } - if (p->Eap_TlsCtx.clientCert.X != NULL) + if (p->Eap_TlsCtx.ClientCert.X != NULL) { - FreeX(p->Eap_TlsCtx.clientCert.X); + FreeX(p->Eap_TlsCtx.ClientCert.X); } if (p->Eap_TlsCtx.Dh != NULL) { diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index ba3ca4ae..f3bbb001 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -18,11 +18,11 @@ #define PPP_PAP_CODE_IS_REQUEST(c) ((c) == PPP_PAP_CODE_REQ) #define PPP_PAP_CODE_IS_RESPONSE(c) ((c) == PPP_PAP_CODE_ACK || (c) == PPP_PAP_CODE_NAK) -#define PPP_CHAP_CODE_IS_REQUEST(c) ((c) == PPP_CHAP_CODE_CHALLENGE || (c) == PPP_CHAP_CODE_SUCCESS || (c) == PPP_CHAP_CODE_FAILURE) -#define PPP_CHAP_CODE_IS_RESPONSE(c) ((c) == PPP_CHAP_CODE_RESPONSE) +#define PPP_CHAP_CODE_IS_REQUEST(c) ((c) == PPP_CHAP_CODE_CHALLENGE || (c) == PPP_CHAP_CODE_SUCCESS || (c) == PPP_CHAP_CODE_FAILURE) +#define PPP_CHAP_CODE_IS_RESPONSE(c) ((c) == PPP_CHAP_CODE_RESPONSE) -#define PPP_EAP_CODE_IS_REQUEST(c) ((c) == PPP_EAP_CODE_REQUEST) -#define PPP_EAP_CODE_IS_RESPONSE(c) ((c) == PPP_EAP_CODE_RESPONSE || (c) == PPP_EAP_CODE_SUCCESS || (c) == PPP_EAP_CODE_FAILURE) +#define PPP_EAP_CODE_IS_REQUEST(c) ((c) == PPP_EAP_CODE_REQUEST) +#define PPP_EAP_CODE_IS_RESPONSE(c) ((c) == PPP_EAP_CODE_RESPONSE || (c) == PPP_EAP_CODE_SUCCESS || (c) == PPP_EAP_CODE_FAILURE) #define PPP_CODE_IS_RESPONSE(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_RESPONSE(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_RESPONSE(c))) #define PPP_CODE_IS_REQUEST(protocol, c) ((((protocol) == PPP_PROTOCOL_LCP || (protocol) == PPP_PROTOCOL_IPCP || (protocol) == PPP_PROTOCOL_IPV6CP) && PPP_LCP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_PAP) && PPP_PAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_CHAP) && PPP_CHAP_CODE_IS_REQUEST(c)) || (((protocol) == PPP_PROTOCOL_EAP) && PPP_EAP_CODE_IS_REQUEST(c))) @@ -52,7 +52,7 @@ #define PPP_PROTOCOL_IPCP 0x8021 #define PPP_PROTOCOL_CHAP 0xc223 #define PPP_PROTOCOL_EAP 0xc227 -#define PPP_PROTOCOL_IPV6CP 0x8057 +#define PPP_PROTOCOL_IPV6CP 0x8057 // PPP protocol (for transfer) #define PPP_PROTOCOL_IP 0x0021 @@ -95,54 +95,54 @@ #define PPP_IPCP_OPTION_WINS2 132 // IPV6CP option type -#define PPP_IPV6CP_OPTION_IID 1 +#define PPP_IPV6CP_OPTION_IID 1 // EAP codes -#define PPP_EAP_CODE_REQUEST 1 -#define PPP_EAP_CODE_RESPONSE 2 -#define PPP_EAP_CODE_SUCCESS 3 -#define PPP_EAP_CODE_FAILURE 4 +#define PPP_EAP_CODE_REQUEST 1 +#define PPP_EAP_CODE_RESPONSE 2 +#define PPP_EAP_CODE_SUCCESS 3 +#define PPP_EAP_CODE_FAILURE 4 // EAP types -#define PPP_EAP_TYPE_IDENTITY 1 -#define PPP_EAP_TYPE_NOTIFICATION 2 -#define PPP_EAP_TYPE_NAK 3 -#define PPP_EAP_TYPE_TLS 13 +#define PPP_EAP_TYPE_IDENTITY 1 +#define PPP_EAP_TYPE_NOTIFICATION 2 +#define PPP_EAP_TYPE_NAK 3 +#define PPP_EAP_TYPE_TLS 13 // EAP-TLS Flags -#define PPP_EAP_TLS_FLAG_NONE 0 -#define PPP_EAP_TLS_FLAG_TLS_LENGTH 1 << 7 -#define PPP_EAP_TLS_FLAG_FRAGMENTED 1 << 6 -#define PPP_EAP_TLS_FLAG_SSLSTARTED 1 << 5 +#define PPP_EAP_TLS_FLAG_NONE 0 +#define PPP_EAP_TLS_FLAG_TLS_LENGTH 1 << 7 +#define PPP_EAP_TLS_FLAG_FRAGMENTED 1 << 6 +#define PPP_EAP_TLS_FLAG_SSLSTARTED 1 << 5 // Authentication protocol #define PPP_LCP_AUTH_PAP PPP_PROTOCOL_PAP #define PPP_LCP_AUTH_CHAP PPP_PROTOCOL_CHAP -#define PPP_LCP_AUTH_EAP PPP_PROTOCOL_EAP +#define PPP_LCP_AUTH_EAP PPP_PROTOCOL_EAP // Algorithm of CHAP #define PPP_CHAP_ALG_MS_CHAP_V2 0x81 // Link status -#define PPP_STATUS_CONNECTED 0x1 -#define PPP_STATUS_BEFORE_AUTH 0x10 -#define PPP_STATUS_AUTHENTICATING 0x11 -#define PPP_STATUS_AUTH_SUCCESS 0x19 -#define PPP_STATUS_NETWORK_LAYER 0x20 -#define PPP_STATUS_CLOSING 0x100 -#define PPP_STATUS_CLOSING_WAIT 0x101 -#define PPP_STATUS_CLOSED 0x110 -#define PPP_STATUS_FAIL 0x1000 -#define PPP_STATUS_AUTH_FAIL 0x1010 +#define PPP_STATUS_CONNECTED 0x1 +#define PPP_STATUS_BEFORE_AUTH 0x10 +#define PPP_STATUS_AUTHENTICATING 0x11 +#define PPP_STATUS_AUTH_SUCCESS 0x19 +#define PPP_STATUS_NETWORK_LAYER 0x20 +#define PPP_STATUS_CLOSING 0x100 +#define PPP_STATUS_CLOSING_WAIT 0x101 +#define PPP_STATUS_CLOSED 0x110 +#define PPP_STATUS_FAIL 0x1000 +#define PPP_STATUS_AUTH_FAIL 0x1010 // Protocol status -#define PPP_PROTO_STATUS_CLOSED 0x0 -#define PPP_PROTO_STATUS_CONFIG 0x1 -#define PPP_PROTO_STATUS_CONFIG_WAIT 0x2 -#define PPP_PROTO_STATUS_OPENED 0x10 -#define PPP_PROTO_STATUS_REJECTED 0x100 +#define PPP_PROTO_STATUS_CLOSED 0x0 +#define PPP_PROTO_STATUS_CONFIG 0x1 +#define PPP_PROTO_STATUS_CONFIG_WAIT 0x2 +#define PPP_PROTO_STATUS_OPENED 0x10 +#define PPP_PROTO_STATUS_REJECTED 0x100 -#define PPP_UNSPECIFIED 0xFFFF +#define PPP_UNSPECIFIED 0xFFFF //// Type @@ -221,13 +221,13 @@ struct PPP_EAP struct PPP_EAP_TLS_CONTEXT { - SSL_PIPE* SslPipe; - DH_CTX* Dh; - struct SslClientCertInfo clientCert; - UCHAR* cachedBufferRecv; - UCHAR* cachedBufferRecvPntr; - UCHAR* cachedBufferSend; - UCHAR* cachedBufferSendPntr; + SSL_PIPE *SslPipe; + DH_CTX *Dh; + struct SslClientCertInfo ClientCert; + UCHAR *CachedBufferRecv; + UCHAR *CachedBufferRecvPntr; + UCHAR *CachedBufferSend; + UCHAR *CachedBufferSendPntr; }; // PPP request resend @@ -316,7 +316,7 @@ struct PPP_SESSION UINT64 UserConnectionTimeout; UINT64 UserConnectionTick; - THREAD* SessionThread; // Thread of the PPP session + THREAD *SessionThread; // Thread of the PPP session }; @@ -339,19 +339,19 @@ bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); -bool PPPProcessEAPResponsePacket(PPP_SESSION* p, PPP_PACKET* pp, PPP_PACKET* req); +bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); // Request packets bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); -bool PPPProcessEAPRequestPacket(PPP_SESSION* p, PPP_PACKET* pp); +bool PPPProcessEAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); // LCP option based packets utility bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET *pp); bool PPPRejectLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate); bool PPPNackLCPOptions(PPP_SESSION *p, PPP_PACKET *pp); -bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET* pp, bool simulate); +bool PPPNackLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate); bool PPPAckLCPOptions(PPP_SESSION *p, PPP_PACKET *pp); bool PPPAckLCPOptionsEx(PPP_SESSION *p, PPP_PACKET *pp, bool simulate); @@ -386,10 +386,10 @@ bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify); bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip); bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify); // EAP packet utilities -bool PPPProcessEAPTlsResponse(PPP_SESSION* p, PPP_EAP* eap_packet, UINT eapTlsSize); +bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSize); PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize); PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UCHAR flags); -PPP_LCP* BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags); +PPP_LCP *BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags); // Other packet utilities PPP_OPTION *PPPGetOptionValue(PPP_LCP *c, UCHAR type); bool IsHubExistsWithLock(CEDAR *cedar, char *hubname); diff --git a/src/Cedar/Proto_SSTP.c b/src/Cedar/Proto_SSTP.c index 83abc3bf..63c2666c 100644 --- a/src/Cedar/Proto_SSTP.c +++ b/src/Cedar/Proto_SSTP.c @@ -97,7 +97,7 @@ void SstpProcessControlPacket(SSTP_SERVER *s, SSTP_PACKET *p) // Process the SSTP received data packet void SstpProcessDataPacket(SSTP_SERVER *s, SSTP_PACKET *p) { - PPP_SESSION* underlyingSession; + PPP_SESSION *underlyingSession; // Validate arguments if (s == NULL || p == NULL || p->IsControl) diff --git a/src/Cedar/Proto_SSTP.h b/src/Cedar/Proto_SSTP.h index 522c0056..8ef8e424 100644 --- a/src/Cedar/Proto_SSTP.h +++ b/src/Cedar/Proto_SSTP.h @@ -116,7 +116,7 @@ struct SSTP_SERVER UINT64 LastRecvTick; // Tick when some data has received at the end bool FlushRecvTube; // Flag whether to flush the reception tube UINT EstablishedCount; // Number of session establishment - PPP_SESSION* PPPSession; // Underlying PPP Session + PPP_SESSION *PPPSession; // Underlying PPP Session }; From 132926ee09878d4a9042e0be4d0abab25269ca6f Mon Sep 17 00:00:00 2001 From: Evengard Date: Sun, 3 May 2020 04:24:01 +0300 Subject: [PATCH 11/13] Fixing alignment of struct on GCC, changing the method to server one --- src/Cedar/Proto_PPP.h | 8 ++++++-- src/Mayaqua/Network.c | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index f3bbb001..311617ba 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -189,7 +189,9 @@ struct PPP_OPTION #ifdef OS_WIN32 #pragma pack(push, 1) -#endif // OS_WIN32 +#else // OS_WIN32 +#pragma pack(1) +#endif // PPP EAP packet @@ -217,7 +219,9 @@ struct PPP_EAP #ifdef OS_WIN32 #pragma pack(pop) -#endif // OS_WIN32 +#else // OS_WIN32 +#pragma pack() +#endif struct PPP_EAP_TLS_CONTEXT { diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index b79238f7..a28aa715 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5729,7 +5729,7 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee { if (server_mode) { - SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method()); + SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_server_method()); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); #ifdef SSL_OP_NO_TLSv1_3 @@ -11792,7 +11792,8 @@ bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x) if (x_copy->root_cert) { X509_STORE* store = SSL_CTX_get_cert_store(ctx); - X509_STORE_add_cert(store, x->x509); + X509_STORE_add_cert(store, x_copy->x509); + X509_free(x_copy->x509); } else { From 8fb456f6a644d8b3a7e9d601cc96e7a7bfff8c5f Mon Sep 17 00:00:00 2001 From: Evengard Date: Sun, 3 May 2020 05:32:01 +0300 Subject: [PATCH 12/13] Fixing a memory leak in SslCertVerifyCallback because of a duplicated callback --- src/Mayaqua/Network.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index a28aa715..717d0f9d 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -5701,10 +5701,17 @@ int SslCertVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) if (cert != NULL) { X *tmpX = X509ToX(cert); // this only wraps cert, but we need to make a copy - X *copyX = CloneX(tmpX); + if (!CompareX(tmpX, clientcert->X)) + { + X* copyX = CloneX(tmpX); + if (clientcert->X != NULL) + { + FreeX(clientcert->X); + } + clientcert->X = copyX; + } tmpX->do_not_free = true; // do not release inner X509 object FreeX(tmpX); - clientcert->X = copyX; } } } From ca1c6a5f3fa5f53eb3dc3fcebd2389b07da12393 Mon Sep 17 00:00:00 2001 From: Evengard Date: Sun, 3 May 2020 14:22:18 +0300 Subject: [PATCH 13/13] Fixing a use of unitialized variable as per CPPCHECK --- src/Cedar/Proto_PPP.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 846e8984..811cad74 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -3013,7 +3013,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi bool isFragmented = false; PPP_LCP *lcp; PPP_EAP *eap; - UCHAR flags; + UCHAR flags = PPP_EAP_TLS_FLAG_NONE; UINT64 sizeLeft = 0; Debug("Got EAP-TLS size=%i\n", eapTlsSize); if (eapTlsSize == 1)