From 27f7d43ff76d533120b5fa26019fca761f945931 Mon Sep 17 00:00:00 2001 From: Davide Beatrici Date: Mon, 11 May 2020 08:23:29 +0200 Subject: [PATCH] Cedar/Proto_OpenVPN: remove UDP system, use the one provided by Proto As a side effect, the DH parameter is now applied to the TCP server as well. Previously, the default value was always used, ignoring the one from the configuration. --- src/Cedar/Proto_OpenVPN.c | 199 ++++++++++++-------------------------- src/Cedar/Proto_OpenVPN.h | 23 +---- 2 files changed, 67 insertions(+), 155 deletions(-) diff --git a/src/Cedar/Proto_OpenVPN.c b/src/Cedar/Proto_OpenVPN.c index 11ca8266..c6acc5fa 100644 --- a/src/Cedar/Proto_OpenVPN.c +++ b/src/Cedar/Proto_OpenVPN.c @@ -23,6 +23,7 @@ PROTO_IMPL *OvsGetProtoImpl() OvsName, OvsIsPacketForMe, OvsProcessData, + OvsProcessDatagrams, OvsBufferLimit, }; @@ -82,14 +83,14 @@ bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size) return false; } -bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send) +bool OvsProcessData(void *param, TCP_RAW_DATA *in, FIFO *out) { bool ret = true; UINT i; OPENVPN_SERVER *server = param; UCHAR buf[OPENVPN_TCP_MAX_PACKET_SIZE]; - if (server == NULL || received_data == NULL || data_to_send == NULL) + if (server == NULL || in == NULL || out == NULL) { return false; } @@ -99,7 +100,7 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send { UDPPACKET *packet; USHORT payload_size, packet_size; - FIFO *fifo = received_data->Data; + FIFO *fifo = in->Data; const UINT fifo_size = FifoSize(fifo); if (fifo_size < sizeof(USHORT)) @@ -133,13 +134,12 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send } // Insert packet into the list - packet = NewUdpPacket(&received_data->SrcIP, received_data->SrcPort, &received_data->DstIP, received_data->DstPort, Clone(buf + sizeof(USHORT), payload_size), payload_size); - packet->Type = OPENVPN_PROTOCOL_TCP; + packet = NewUdpPacket(&in->SrcIP, in->SrcPort, &in->DstIP, in->DstPort, Clone(buf + sizeof(USHORT), payload_size), payload_size); Add(server->RecvPacketList, packet); } // Process the list of received datagrams - OvsRecvPacket(server, server->RecvPacketList); + OvsRecvPacket(server, server->RecvPacketList, OPENVPN_PROTOCOL_TCP); // Release the received packet list for (i = 0; i < LIST_NUM(server->RecvPacketList); ++i) @@ -158,10 +158,10 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send // Store the size in the TCP send queue first USHORT us = Endian16((USHORT)p->Size); - WriteFifo(data_to_send, &us, sizeof(USHORT)); + WriteFifo(out, &us, sizeof(USHORT)); // Write the data body - WriteFifo(data_to_send, p->Data, p->Size); + WriteFifo(out, p->Data, p->Size); // Packet release FreeUdpPacket(p); @@ -171,7 +171,8 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send if (server->Giveup <= server->Now) { - for (UINT i = 0; i < LIST_NUM(server->SessionList); ++i) + UINT i; + for (i = 0; i < LIST_NUM(server->SessionList); ++i) { OPENVPN_SESSION *se = LIST_DATA(server->SessionList, i); @@ -187,6 +188,47 @@ bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send return ret; } +bool OvsProcessDatagrams(void *param, LIST *in, LIST *out) +{ + UINT i; + LIST *to_send; + OPENVPN_SERVER *server = param; + + if (server == NULL || in == NULL || out == NULL) + { + return false; + } + + OvsRecvPacket(server, in, OPENVPN_PROTOCOL_UDP); + + to_send = server->SendPacketList; + + for (i = 0; i < LIST_NUM(to_send); ++i) + { + Add(out, LIST_DATA(to_send, i)); + } + + DeleteAll(server->SendPacketList); + + if (server->Giveup <= server->Now) + { + UINT i; + for (i = 0; i < LIST_NUM(server->SessionList); ++i) + { + OPENVPN_SESSION *se = LIST_DATA(server->SessionList, i); + + if (se->Established) + { + return server->DisconnectCount < 1; + } + } + + return false; + } + + return true; +} + void OvsBufferLimit(void *param, const bool reached) { if (param == NULL) @@ -507,7 +549,7 @@ final: } // Process the received packet -void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p) +void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol) { OPENVPN_CHANNEL *c; OPENVPN_SESSION *se; @@ -519,7 +561,7 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p) } // Search for the session - se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, p->Type); + se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, protocol); if (se == NULL) { return; @@ -749,8 +791,13 @@ void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN // Create an SSL pipe Lock(s->Cedar->lock); { - bool cert_verify = true; - c->SslPipe = NewSslPipeEx(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh, cert_verify, &c->ClientCert); + if (s->Dh->Size != s->Cedar->DhParamBits) + { + DhFree(s->Dh); + s->Dh = DhNewFromBits(s->Cedar->DhParamBits); + } + + c->SslPipe = NewSslPipeEx(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh, true, &c->ClientCert); } Unlock(s->Cedar->lock); @@ -2165,7 +2212,7 @@ OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_ } // Receive packets in the OpenVPN server -void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list) +void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol) { UINT i, j; LIST *delete_session_list = NULL; @@ -2197,7 +2244,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list) { UDPPACKET *p = LIST_DATA(recv_packet_list, i); - OvsProceccRecvPacket(s, p); + OvsProceccRecvPacket(s, p, protocol); } // Treat for all sessions and all channels @@ -2908,7 +2955,7 @@ OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOC OvsLog(s, NULL, NULL, "LO_START"); - s->Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT); + s->Dh = DhNewFromBits(cedar->DhParamBits); return s; } @@ -2956,123 +3003,3 @@ void FreeOpenVpnServer(OPENVPN_SERVER *s) Free(s); } - -// UDP reception procedure -void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list) -{ - OPENVPN_SERVER_UDP *us; - // Validate arguments - if (u == NULL || packet_list == NULL) - { - return; - } - - us = (OPENVPN_SERVER_UDP *)u->Param; - - if (us->OpenVpnServer != NULL) - { - { - u->PollMyIpAndPort = false; - - ClearStr(us->Cedar->OpenVPNPublicPorts, sizeof(us->Cedar->OpenVPNPublicPorts)); - } - - OvsRecvPacket(us->OpenVpnServer, packet_list); - - UdpListenerSendPackets(u, us->OpenVpnServer->SendPacketList); - DeleteAll(us->OpenVpnServer->SendPacketList); - } -} - -// Create an OpenVPN server (UDP mode) -OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar) -{ - OPENVPN_SERVER_UDP *u; - // Validate arguments - if (cedar == NULL) - { - return NULL; - } - - u = ZeroMalloc(sizeof(OPENVPN_SERVER_UDP)); - - u->Cedar = cedar; - - AddRef(u->Cedar->ref); - - // Create a UDP listener - u->UdpListener = NewUdpListenerEx(OpenVpnServerUdpListenerProc, u, &cedar->Server->ListenIP, OPENVPN_PROTOCOL_UDP); - - // Create an OpenVPN server - u->OpenVpnServer = NewOpenVpnServer(cedar, u->UdpListener->Interrupts, u->UdpListener->Event); - - return u; -} - -void OpenVpnServerUdpSetDhParam(OPENVPN_SERVER_UDP *u, DH_CTX *dh) -{ - // Validate arguments - if (u == NULL) { - return; - } - - if (u->OpenVpnServer->Dh) - { - DhFree(u->OpenVpnServer->Dh); - } - - u->OpenVpnServer->Dh = dh; -} - -// Apply the port list to the OpenVPN server -void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list, IP *listen_ip) -{ - LIST *o; - UINT i; - // Validate arguments - if (u == NULL) - { - return; - } - - DeleteAllPortFromUdpListener(u->UdpListener); - - if (u->UdpListener != NULL && listen_ip != NULL) - { - Copy(&u->UdpListener->ListenIP, listen_ip, sizeof(IP)); - } - - o = StrToIntList(port_list, true); - - for (i = 0;i < LIST_NUM(o);i++) - { - UINT port = *((UINT *)LIST_DATA(o, i)); - - if (port >= 1 && port <= 65535) - { - AddPortToUdpListener(u->UdpListener, port); - } - } - - ReleaseIntList(o); -} - -// Release the OpenVPN server (UDP mode) -void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u) -{ - // Validate arguments - if (u == NULL) - { - return; - } - - // Stop the UDP listener - FreeUdpListener(u->UdpListener); - - // Release the OpenVPN server - FreeOpenVpnServer(u->OpenVpnServer); - - ReleaseCedar(u->Cedar); - - Free(u); -} diff --git a/src/Cedar/Proto_OpenVPN.h b/src/Cedar/Proto_OpenVPN.h index 7c88e6ce..39324b84 100644 --- a/src/Cedar/Proto_OpenVPN.h +++ b/src/Cedar/Proto_OpenVPN.h @@ -204,15 +204,6 @@ struct OPENVPN_SERVER UINT SessionEstablishedCount; // Number of session establishment }; -// OpenVPN server (UDP mode) -struct OPENVPN_SERVER_UDP -{ - CEDAR *Cedar; - UDPLISTENER *UdpListener; // UDP listener - OPENVPN_SERVER *OpenVpnServer; // OpenVPN server - UINT64 VgsNextGetPublicPortsTick; -}; - // OpenVPN Default Client Option String #define OVPN_DEF_CLIENT_OPTION_STRING "dev-type tun,link-mtu 1500,tun-mtu 1500,cipher AES-128-CBC,auth SHA1,keysize 128,key-method 2,tls-client" @@ -222,20 +213,16 @@ bool OvsInit(void **param, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se); void OvsFree(void *param); char *OvsName(); bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size); -bool OvsProcessData(void *param, TCP_RAW_DATA *received_data, FIFO *data_to_send); +bool OvsProcessData(void *param, TCP_RAW_DATA *in, FIFO *out); +bool OvsProcessDatagrams(void *param, LIST *in, LIST *out); void OvsBufferLimit(void *param, const bool reached); bool OvsIsOk(void *param); UINT OvsEstablishedSessions(void *param); -OPENVPN_SERVER_UDP *NewOpenVpnServerUdp(CEDAR *cedar); -void FreeOpenVpnServerUdp(OPENVPN_SERVER_UDP *u); -void OpenVpnServerUdpListenerProc(UDPLISTENER *u, LIST *packet_list); -void OvsApplyUdpPortList(OPENVPN_SERVER_UDP *u, char *port_list, IP *listen_ip); - OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event); void FreeOpenVpnServer(OPENVPN_SERVER *s); -void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list); -void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p); +void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol); +void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol); int OvsCompareSessionList(void *p1, void *p2); OPENVPN_SESSION *OvsSearchSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol); OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, UINT protocol); @@ -279,6 +266,4 @@ UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c); CIPHER *OvsGetCipher(char *name); MD *OvsGetMd(char *name); -void OpenVpnServerUdpSetDhParam(OPENVPN_SERVER_UDP *u, DH_CTX *dh); - #endif // PROTO_OPENVPN_H