//----- Include files --------------------------------------------------------- #include #include // Needed for exit() #include #include #include #include #include #include #include #include "network.hpp" #ifdef UNIX #include #endif // Hazardous globals char hazardous_contents_CS_01[256] = "password.txt"; char hazardous_contents_CS_02[256] = "admin.config"; int main(void) { /* FOR WIN ------------------------------------------------------------- */ #ifdef WIN WORD wVersionRequested = MAKEWORD(1, 1); // Stuff for WSA functions WSADATA wsaData; int wsResult; // Stuff for WSA functions wsResult = WSAStartup(wVersionRequested, &wsaData); if (wsResult != 0) { printf("WSAStartup failed: %d\n", wsResult); return 1; } #endif /* --------------------------------------------------------------------- */ strcpy(hazardous_contents_CS_01, "password.txt"); strcpy(hazardous_contents_CS_02, "admin.config"); std::vector> pending_futures; Server proxy(kProxyPort); Client browser; Client webserver; // Main loop to listen, accept, and then spin-off a thread to handle the GET while (1) { if (browser.ConnectFrom(proxy.socketFD) != 0) { std::cerr << "ERROR - Unable to create socket to client" << std::endl; continue; } if (webserver.ConnectTo(kWebserverPort) != 0) { std::cerr << "ERROR - Unable to connect to webserver" << std::endl; continue; } auto newThreadRequest1 = std::async(std::launch::async, PipeSockets, browser.socketFD, webserver.socketFD); auto newThreadRequest2 = std::async(std::launch::async, ProxySockets, webserver.socketFD, browser.socketFD); pending_futures.push_back(std::move(newThreadRequest1)); pending_futures.push_back(std::move(newThreadRequest2)); } proxy.Close(); return 0; } void PipeSockets(int sender_s, int receiver_s) { char in_buf[BUF_SIZE]; // Input buffer for GET resquest #ifdef UNIX ssize_t buf_len; // Buffer length for file reads #endif #ifdef WIN SSIZE_T buf_len; // Buffer length for file reads #endif // Pass GET along from browser to server std::cout << "Attempting to send data to receiver" << std::endl; do { // Receive buf_len = recv(sender_s, in_buf, BUF_SIZE, 0); std::cout << "LOG (info) - pipe packet recv size: " << buf_len << '\n'; if (buf_len == -1) { std::cout << "ERROR (info) - recv" << std::endl; #ifdef WIN closesocket(sender_s); closesocket(receiver_s); #endif #ifdef UNIX close(sender_s); close(receiver_s); #endif return; } if (buf_len == 0) { continue; } // Hazardous check if ((strstr(in_buf, hazardous_contents_CS_01) != NULL) || (strstr(in_buf, hazardous_contents_CS_02) != NULL)) { std::cerr << "LOG (warn) - Hazardous contents detected" << std::endl; strcpy(in_buf, FORBIDDEN_403); send(sender_s, in_buf, strlen(in_buf), 0); strcpy(in_buf, MESS_403); send(sender_s, in_buf, strlen(in_buf), 0); #ifdef WIN closesocket(sender_s); closesocket(receiver_s); #endif #ifdef UNIX close(sender_s); close(receiver_s); #endif return; } // Send buf_len = send(receiver_s, in_buf, buf_len, 0); std::cout << "LOG (info) - pipe packet send size: " << buf_len << '\n'; } while (buf_len == BUF_SIZE); std::cout << "Sent data to receiver" << std::endl; } void ProxySockets(int sender_s, int receiver_s) { char out_buf[BUF_SIZE]; // Output buffer for HTML response #ifdef UNIX ssize_t buf_len; // Buffer length for file reads #endif #ifdef WIN SSIZE_T buf_len; // Buffer length for file reads #endif // Pass response along from server to browser std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Attempting to send to browser" << std::endl; do { // Receive buf_len = recv(sender_s, out_buf, BUF_SIZE, 0); std::cout << "LOG (info) - proxy packet recv size: " << buf_len << '\n'; if (buf_len == -1) { std::cout << "ERROR (info) - recv -1" << std::endl; return; } // Hazardous check if ((strstr(out_buf, hazardous_contents_CS_01) != NULL) || (strstr(out_buf, hazardous_contents_CS_02) != NULL)) { std::cerr << "LOG (warn) - Hazardous contents detected" << std::endl; strcpy(out_buf, FORBIDDEN_403); send(receiver_s, out_buf, strlen(out_buf), 0); strcpy(out_buf, MESS_403); send(receiver_s, out_buf, strlen(out_buf), 0); #ifdef WIN closesocket(sender_s); closesocket(receiver_s); #endif #ifdef UNIX close(sender_s); close(receiver_s); #endif return; } // Send buf_len = send(receiver_s, out_buf, buf_len, 0); if (buf_len == 96) { break; } std::cout << "LOG (info) - proxy packet send size: " << buf_len << '\n'; } while ((buf_len == BUF_SIZE) || (buf_len == 40)); std::cout << "Sent to browser" << std::endl; #ifdef WIN closesocket(sender_s); closesocket(receiver_s); #endif #ifdef UNIX close(sender_s); close(receiver_s); #endif } Client::Client(void) { addressLength = sizeof(address); address.sin_family = AF_INET; } bool Client::ConnectFrom(int serverFD) { socketFD = accept(serverFD, (struct sockaddr*)&address, &addressLength); if (socketFD == -1) { return 1; } return 0; } bool Client::ConnectTo(int portNumber) { std::cout << "Attempting to connect to " << kWebserverIP << " on " << portNumber << std::endl; address.sin_port = htons(portNumber); #ifdef WIN if (InetPton(address.sin_family, (PCSTR)kWebserverIP, &address.sin_addr) <= 0) { #endif #ifdef UNIX if (inet_pton(address.sin_family, kWebserverIP, &address.sin_addr) <= 0) { #endif std::cerr << "ERROR (info) - inet_pton" << std::endl; return 1; } socketFD = socket(address.sin_family, SOCK_STREAM, 0); if (connect(socketFD, (struct sockaddr*)&address, addressLength) == -1) { std::cerr << "ERROR (info) - connect" << std::endl; return 1; } std::cout << "Connection successful" << std::endl; return 0; } Server::Server(int portNumber) { std::cout << "Opening the server" << std::endl; #ifdef WIN socketFD = socket(AF_INET, SOCK_STREAM, 0); #endif #ifdef UNIX socketFD = socket(AF_INET, SOCK_STREAM, 0); #endif if (socketFD == -1) { std::cerr << "ERROR - Unable to create socket on server" << std::endl; exit(1); } address.sin_family = AF_INET; address.sin_port = htons(portNumber); address.sin_addr.s_addr = htonl(INADDR_ANY); // Create a socket, fill-in address information, and then bind it if (bind(socketFD, (struct sockaddr*)&address, sizeof(address)) == -1) { std::cerr << "ERROR - Unable to bind socket" << std::endl; exit(1); } // Listen for connections and then accept listen(socketFD, 100); std::cout << "Server is now open" << std::endl; } void Server::Close(void) { std::cout << "Closing the server" << std::endl; #ifdef WIN closesocket(socketFD); WSACleanup(); #endif #ifdef UNIX close(socketFD); #endif }