From 9516017e8faf9331ece378ab3eaaa940a3ade007 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 10:59:57 +0200 Subject: [PATCH 01/13] build(openSSL): add rule to check and eventually install openSSL --- Makefile | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 657d183e..81f8386e 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,23 @@ ifeq ($(UNAME_S), Darwin) LDFLAGS += -fsanitize=address endif +# Check if pkg-config is available and OpenSSL is installed +PKGCONFIG := $(shell which pkg-config) +USE_LOCAL_OPENSSL := 0 +ifneq ($(PKGCONFIG),) + PKGCONFIG_OPENSSL := $(shell pkg-config --exists openssl && echo 1 || echo 0) + ifeq ($(PKGCONFIG_OPENSSL), 0) + USE_LOCAL_OPENSSL := 1 + else + OPENSSL_INCLUDE := $(shell pkg-config --cflags-only-I openssl | sed 's/-I//') + OPENSSL_LIB := $(shell pkg-config --libs-only-L openssl | sed 's/-L//') + CXXFLAGS += -I$(OPENSSL_INCLUDE) + LDFLAGS += -L$(OPENSSL_LIB) -lssl -lcrypto + endif +else + USE_LOCAL_OPENSSL := 1 +endif + # Source and Object Files SRCS = src/main.cpp \ src/Parser.cpp \ @@ -39,7 +56,29 @@ OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o) TARGET = webserv # Build Rules -all: $(TARGET) +all: check_openssl $(TARGET) + +# Rule to check and install OpenSSL if needed +check_openssl: +ifeq ($(INSTALL_OPENSSL), 1) + @echo "OpenSSL not found. Installing locally..." + @$(MAKE) install_openssl +else + @echo "Using system OpenSSL." +endif + +# Rule to download, build, and install OpenSSL locally +install_openssl: + @mkdir -p openssl + @cd openssl && \ + wget https://www.openssl.org/source/openssl-1.1.1.tar.gz && \ + tar -xzf openssl-1.1.1.tar.gz && \ + cd openssl-1.1.1 && \ + ./config --prefix=$(LOCAL_OPENSSL_DIR) --openssldir=$(LOCAL_OPENSSL_DIR) no-shared && \ + make && \ + make install && \ + cd ../.. && \ + rm -rf openssl # Ensure the necessary directories exist before compiling anything $(OBJDIR)/%.o: %.cpp @@ -60,4 +99,4 @@ fclean: clean re: fclean all -.PHONY: all clean fclean re \ No newline at end of file +.PHONY: all clean fclean re check_openssl install_openssl \ No newline at end of file From ef792d83555a1f0ae35dc24902928a6b81bfd138 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 11:18:19 +0200 Subject: [PATCH 02/13] chore(language server): add path to openssl --- .vscode/c_cpp_propertied.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.vscode/c_cpp_propertied.json b/.vscode/c_cpp_propertied.json index 914e6796..257f7f25 100644 --- a/.vscode/c_cpp_propertied.json +++ b/.vscode/c_cpp_propertied.json @@ -2,13 +2,22 @@ "configurations": [ { "name": "Mac", + "includePath": ["${workspaceFolder}/**", "usr/local/opt/openssl/include"], + "macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c99", "cppStandard": "c++98", - "includePath": ["${workspaceFolder}/**"] + "intelliSenseMode": "macos-clang-x64" }, { "name": "Linux", "cppStandard": "c++98", - "includePath": ["${workspaceFolder}/**"] + "includePath": ["${workspaceFolder}/**", "/usr/include/openssl"], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c99", + "intelliSenseMode": "linux-gcc-x64" } ], "version": 4, From 8424b18fe11776476b0b1aa6b25ba6d2e0a39243 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 11:49:46 +0200 Subject: [PATCH 03/13] feat(ssl): add SSLContext object and wire up with main --- Makefile | 14 +++++++++++--- include/webserv.hpp | 2 ++ src/main.cpp | 8 ++++++++ src/ssl/SSLContext.cpp | 24 ++++++++++++++++++++++++ src/ssl/SSLContext.hpp | 20 ++++++++++++++++++++ src/ssl/SSLManager.cpp | 23 +++++++++++++++++++++++ src/ssl/SSLManager.hpp | 19 +++++++++++++++++++ 7 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/ssl/SSLContext.cpp create mode 100644 src/ssl/SSLContext.hpp create mode 100644 src/ssl/SSLManager.cpp create mode 100644 src/ssl/SSLManager.hpp diff --git a/Makefile b/Makefile index 81f8386e..891e1036 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ # Compiler and Flags CXX = c++ -CXXFLAGS = -Wall -Wextra -Werror -std=c++98 -I. -Iinclude -Isrc -Isrc/events -g +CXXFLAGS = -Wall -Wextra -Werror -std=c++98 -I. -Iinclude -Isrc -Isrc/events -Isrc/ssl -g DEPFLAGS = -MMD -MP +LDFLAGS = UNAME_S := $(shell uname -s) # Additional Flags for macOS @@ -27,6 +28,11 @@ else USE_LOCAL_OPENSSL := 1 endif +# Paths for local OpenSSL installation +LOCAL_OPENSSL_DIR := $(CURDIR)/local/openssl +LOCAL_INCLUDE := $(LOCAL_OPENSSL_DIR)/include +LOCAL_LIB := $(LOCAL_OPENSSL_DIR)/lib + # Source and Object Files SRCS = src/main.cpp \ src/Parser.cpp \ @@ -48,7 +54,9 @@ SRCS = src/main.cpp \ src/ServerSocket.cpp \ src/Listen.cpp \ src/events/EventManager.cpp \ - src/events/ServerEventListener.cpp + src/events/ServerEventListener.cpp \ + src/ssl/SSLManager.cpp \ + src/ssl/SSLContext.cpp OBJDIR = obj OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o) @@ -87,7 +95,7 @@ $(OBJDIR)/%.o: %.cpp # Linking the main target $(TARGET): $(OBJS) - $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) + $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) # Cleaning up the build clean: diff --git a/include/webserv.hpp b/include/webserv.hpp index dacc21f3..9e38a8fc 100644 --- a/include/webserv.hpp +++ b/include/webserv.hpp @@ -1,6 +1,8 @@ #ifndef WEBSERV_H #define WEBSERV_H +#include +#include #include #include #include diff --git a/src/main.cpp b/src/main.cpp index a0a18ab8..182a587f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,8 @@ #include "webserv.hpp" #include "EventManager.hpp" #include "ServerEventListener.hpp" +#include "SSLManager.hpp" +#include "SSLContext.hpp" int main(int argc, char **argv) { @@ -29,6 +31,12 @@ int main(int argc, char **argv) std::cout << &webserv.getEventManager() << std::endl; + // Initialize SSLManager and SSLContext + SSLManager *sslManager = SSLManager::getInstance(); + (void)sslManager; + SSLContext sslContext; + (void)sslContext; + webserv.startListening(); webserv.startPollEventLoop(); diff --git a/src/ssl/SSLContext.cpp b/src/ssl/SSLContext.cpp new file mode 100644 index 00000000..d61f28b6 --- /dev/null +++ b/src/ssl/SSLContext.cpp @@ -0,0 +1,24 @@ +#include "SSLContext.hpp" + +SSLContext::SSLContext() +{ + ctx = SSL_CTX_new(SSLv23_client_method()); + if (!ctx) + { + throw std::runtime_error("Unable to create SSL context"); + } + SSL_CTX_set_ecdh_auto(ctx, 1); +} + +SSLContext::~SSLContext() +{ + if (ctx) + { + SSL_CTX_free(ctx); + } +} + +SSL_CTX *SSLContext::getContext() +{ + return ctx; +} diff --git a/src/ssl/SSLContext.hpp b/src/ssl/SSLContext.hpp new file mode 100644 index 00000000..304c1d21 --- /dev/null +++ b/src/ssl/SSLContext.hpp @@ -0,0 +1,20 @@ +#ifndef SSL_CONTEXT_HPP +#define SSL_CONTEXT_HPP + +#include +#include +#include + +class SSLContext +{ + public: + SSLContext(); + ~SSLContext(); + + SSL_CTX *getContext(); + + private: + SSL_CTX *ctx; +}; + +#endif // SSL_CONTEXT_HPP diff --git a/src/ssl/SSLManager.cpp b/src/ssl/SSLManager.cpp new file mode 100644 index 00000000..4f7e7f94 --- /dev/null +++ b/src/ssl/SSLManager.cpp @@ -0,0 +1,23 @@ +#include "SSLManager.hpp" + +SSLManager *SSLManager::getInstance() +{ + static SSLManager instance; + return &instance; +} + +SSLManager::SSLManager() +{ + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); +} + +SSLManager::~SSLManager() +{ + ERR_free_strings(); + EVP_cleanup(); + // Additional cleanup can be added here + // CRYPTO_cleanup_all_ex_data(); + // SSL_COMP_free_compression_methods(); +} \ No newline at end of file diff --git a/src/ssl/SSLManager.hpp b/src/ssl/SSLManager.hpp new file mode 100644 index 00000000..885e2cea --- /dev/null +++ b/src/ssl/SSLManager.hpp @@ -0,0 +1,19 @@ +#ifndef SSL_MANAGER_HPP +#define SSL_MANAGER_HPP + +#include +#include + +class SSLManager +{ + public: + static SSLManager *getInstance(); + + private: + SSLManager(); + ~SSLManager(); + SSLManager(const SSLManager &other); + SSLManager &operator=(const SSLManager &other); +}; + +#endif // SSL_MANAGER_HPP From 6624460efb76f877438bd60f3dc59b3f6d1573c1 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 12:19:21 +0200 Subject: [PATCH 04/13] chore(language server): fix path for headers in the vscode json --- .vscode/c_cpp_propertied.json | 37 ----------------------- .vscode/c_cpp_properties.json | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 37 deletions(-) delete mode 100644 .vscode/c_cpp_propertied.json create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_propertied.json b/.vscode/c_cpp_propertied.json deleted file mode 100644 index 257f7f25..00000000 --- a/.vscode/c_cpp_propertied.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": ["${workspaceFolder}/**", "usr/local/opt/openssl/include"], - "macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"], - "defines": [], - "compilerPath": "/usr/bin/clang", - "cStandard": "c99", - "cppStandard": "c++98", - "intelliSenseMode": "macos-clang-x64" - }, - { - "name": "Linux", - "cppStandard": "c++98", - "includePath": ["${workspaceFolder}/**", "/usr/include/openssl"], - "defines": [], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c99", - "intelliSenseMode": "linux-gcc-x64" - } - ], - "version": 4, - "workbench.colorCustomizations": { - "activityBar.background": "#063516", - "titleBar.activeBackground": "#094B1F", - "titleBar.activeForeground": "#F3FEF6" - }, - "files.associations": { - "*.cpp": "cpp", - "*.h": "cpp", - "*.md": "markdown", - "*.sh": "shellscript" - }, - "C_Cpp.clang_format_style": "file", - "C_Cpp.clang_format_fallbackStyle": "Google" -} diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..6e07fc23 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,57 @@ +{ + "configurations": [ + { + "name": "Mac-ARM", + "includePath": [ + "${workspaceFolder}/**", + "/usr/local/opt/openssl/include", + "/opt/homebrew/opt/openssl/include", + "/opt/homebrew/include" + ], + "macFrameworkPath": ["/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/System/Library/Frameworks"], + "defines": [], + "compilerPath": "/Users/stefano/.brew/opt/llvm/bin/clang", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "macos-clang-arm64" + }, + { + "name": "Mac-x86", + "includePath": [ + "${workspaceFolder}/**", + "/usr/local/opt/openssl/include", + "/opt/homebrew/opt/openssl/include", + "/opt/homebrew/include" + ], + "macFrameworkPath": ["/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/System/Library/Frameworks"], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "macos-clang-x64" + }, + { + "name": "Linux", + "cppStandard": "c++98", + "includePath": ["${workspaceFolder}/**", "/usr/include/openssl"], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c99", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4, + "workbench.colorCustomizations": { + "activityBar.background": "#063516", + "titleBar.activeBackground": "#094B1F", + "titleBar.activeForeground": "#F3FEF6" + }, + "files.associations": { + "*.cpp": "cpp", + "*.h": "cpp", + "*.md": "markdown", + "*.sh": "shellscript" + }, + "C_Cpp.clang_format_style": "file", + "C_Cpp.clang_format_fallbackStyle": "Google" +} From 59fb09f35918b98054b4e8adfeb9391fca69c427 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 12:25:10 +0200 Subject: [PATCH 05/13] chore(Server): small clean up --- src/Server.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Server.cpp b/src/Server.cpp index e4bc5c84..1c2d721a 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -416,7 +416,9 @@ void Server::buildCGIResponse(Connection &conn, HTTPResponse &response) void Server::writeToClient(Connection &conn, size_t &i, HTTPResponse &response) { - std::cout << "\033[1;36m" << "Entering writeToClient" << "\033[0m" << std::endl; + std::cout << "\033[1;36m" + << "Entering writeToClient" + << "\033[0m" << std::endl; std::cout << response << std::endl; static int sendResponseCounter = 0; bool isLastSend = false; @@ -458,7 +460,9 @@ void Server::writeToClient(Connection &conn, size_t &i, HTTPResponse &response) void Server::closeClientConnection(Connection &conn, size_t &i) { - std::cout << "\033[1;36m" << "Entering closeClientConnection" << "\033[0m" << std::endl; + std::cout << "\033[1;36m" + << "Entering closeClientConnection" + << "\033[0m" << std::endl; // TODO: should we close it with the Destructor of the Connection class? close(conn.getPollFd().fd); _FDs.erase(_FDs.begin() + i); @@ -473,7 +477,9 @@ void Server::handleConnection(Connection &conn, size_t &i) HTTPResponse &response = _connections[i].getResponse(); // printFrame("CLIENT SOCKET EVENT", true); - std::cout << "\033[1;36m" << "Entering handleConnection" << "\033[0m" << std::endl; + std::cout << "\033[1;36m" + << "Entering handleConnection" + << "\033[0m" << std::endl; conn.setHasReadSocket(false); std::cout << "Has finished reading: " << conn.getHasFinishedReading() << std::endl; @@ -722,8 +728,6 @@ void Server::addServerSocketsPollFdToVectors() void Server::acceptNewConnection(Connection &conn) { - // struct sockaddr_in clientAddress; - // We choose sockaddr_storage to be able to handle both IPv4 and IPv6 // printFrame("SERVER SOCKET EVENT", true); struct sockaddr_storage clientAddress; socklen_t ClientAddrLen = sizeof(clientAddress); From 8c917ca8c552fb04254cad66d720052a5cbf35e6 Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 12:37:36 +0200 Subject: [PATCH 06/13] chore(debug): overload log function so that it takes colors --- src/Debug.cpp | 10 ++++++++-- src/Debug.hpp | 1 + src/Server.cpp | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Debug.cpp b/src/Debug.cpp index 678626b2..42af1827 100644 --- a/src/Debug.cpp +++ b/src/Debug.cpp @@ -1,4 +1,5 @@ #include "Debug.hpp" +#include "webserv.hpp" // In C++98 the initialization of static members must be done outside the class definition. bool Debug::debugEnabled = true; @@ -38,7 +39,7 @@ void Debug::removeLevel(Debug::Level level) debugLevel = static_cast(debugLevel & ~level); } -void Debug::log(const std::string &message, Debug::Level paramLevel) +void Debug::log(const std::string &message, Debug::Level paramLevel, const std::string &color) { if (!debugEnabled) { @@ -46,6 +47,11 @@ void Debug::log(const std::string &message, Debug::Level paramLevel) } if (debugLevel & paramLevel) { - std::cout << message << std::endl; + std::cout << color << message << "\033[0m" << std::endl; } } + +void Debug::log(const std::string &message, Debug::Level paramLevel) +{ + log(message, paramLevel, RESET); +} diff --git a/src/Debug.hpp b/src/Debug.hpp index 45016995..95f97b39 100644 --- a/src/Debug.hpp +++ b/src/Debug.hpp @@ -34,6 +34,7 @@ class Debug static void addLevel(Level level); static void removeLevel(Level leve); static void log(const std::string &message, Debug::Level paramLevel); + static void log(const std::string &message, Debug::Level paramLevel, const std::string &color); }; #endif diff --git a/src/Server.cpp b/src/Server.cpp index 1c2d721a..a7af3dbb 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -728,7 +728,7 @@ void Server::addServerSocketsPollFdToVectors() void Server::acceptNewConnection(Connection &conn) { - // printFrame("SERVER SOCKET EVENT", true); + printFrame("SERVER SOCKET EVENT", true); struct sockaddr_storage clientAddress; socklen_t ClientAddrLen = sizeof(clientAddress); Debug::log("New connection detected", Debug::SERVER); From c029abbb858391d47f1d7c01d67806aefd1c8bfa Mon Sep 17 00:00:00 2001 From: 552020 Date: Thu, 23 May 2024 12:52:37 +0200 Subject: [PATCH 07/13] chore(debug): remove printFrame and embed it in Debug::log --- src/Debug.cpp | 28 ++++++++++++++++++++++------ src/Debug.hpp | 9 +++++++-- src/Server.cpp | 10 ++++------ src/server_utils.cpp | 10 ---------- src/server_utils.hpp | 1 - 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/Debug.cpp b/src/Debug.cpp index 42af1827..2e239a70 100644 --- a/src/Debug.cpp +++ b/src/Debug.cpp @@ -39,7 +39,17 @@ void Debug::removeLevel(Debug::Level level) debugLevel = static_cast(debugLevel & ~level); } -void Debug::log(const std::string &message, Debug::Level paramLevel, const std::string &color) +void printFrame(const std::string &message, const std::string &color, bool blinking) +{ + std::string blink = blinking ? BLINKING : ""; + std::cout << color << blink; + std::cout << std::setw(10) << ' ' << "***************************" << std::endl; + std::cout << std::setw(10) << ' ' << "* " << message << " *" << std::endl; + std::cout << std::setw(10) << ' ' << "***************************" << std::endl; + std::cout << RESET; +} + +void Debug::log(const std::string &message, Debug::Level paramLevel, const std::string &color, bool bliking, bool frame) { if (!debugEnabled) { @@ -47,11 +57,17 @@ void Debug::log(const std::string &message, Debug::Level paramLevel, const std:: } if (debugLevel & paramLevel) { - std::cout << color << message << "\033[0m" << std::endl; + std::string blink = bliking ? BLINKING : ""; + if (frame) + { + printFrame(message, color, bliking); + } + else + std::cout << color << blink << message << RESET << std::endl; } } -void Debug::log(const std::string &message, Debug::Level paramLevel) -{ - log(message, paramLevel, RESET); -} +// void Debug::log(const std::string &message, Debug::Level paramLevel) +// { +// log(message, paramLevel, RESET); +// } diff --git a/src/Debug.hpp b/src/Debug.hpp index 95f97b39..f965831d 100644 --- a/src/Debug.hpp +++ b/src/Debug.hpp @@ -2,6 +2,7 @@ #define DEBUG_HPP #include +#include #include class Debug @@ -33,8 +34,12 @@ class Debug static void setLevel(Level level); static void addLevel(Level level); static void removeLevel(Level leve); - static void log(const std::string &message, Debug::Level paramLevel); - static void log(const std::string &message, Debug::Level paramLevel, const std::string &color); + // static void log(const std::string &message, Debug::Level paramLevel); + static void log(const std::string &message, + Debug::Level paramLevel, + const std::string &color = "\033[0m", + bool bliking = false, + bool frame = false); }; #endif diff --git a/src/Server.cpp b/src/Server.cpp index a7af3dbb..13de8a80 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -77,7 +77,7 @@ void Server::startPollEventLoop() << " Waiting for new connection or Polling +++++++++++++++" << RESET << std::endl; int ret = poll(_FDs.data(), _FDs.size(), timeout); pollCounter++; - // printFrame("POLL EVENT DETECTED", true); + Debug::log("Poll event detected", Debug::SERVER, YELLOW, false, true); // printConnections("AFTER POLL", _FDs, _connections, true); if (ret > 0) { @@ -476,10 +476,8 @@ void Server::handleConnection(Connection &conn, size_t &i) HTTPRequest &request = _connections[i].getRequest(); HTTPResponse &response = _connections[i].getResponse(); - // printFrame("CLIENT SOCKET EVENT", true); - std::cout << "\033[1;36m" - << "Entering handleConnection" - << "\033[0m" << std::endl; + Debug::log("Client socket event", Debug::SERVER, CYAN, false, true); + Debug::log("Entering handleConnection", Debug::SERVER); conn.setHasReadSocket(false); std::cout << "Has finished reading: " << conn.getHasFinishedReading() << std::endl; @@ -728,7 +726,7 @@ void Server::addServerSocketsPollFdToVectors() void Server::acceptNewConnection(Connection &conn) { - printFrame("SERVER SOCKET EVENT", true); + Debug::log("SERVER SOCKET EVENT", Debug::SERVER, CYAN, false, true); struct sockaddr_storage clientAddress; socklen_t ClientAddrLen = sizeof(clientAddress); Debug::log("New connection detected", Debug::SERVER); diff --git a/src/server_utils.cpp b/src/server_utils.cpp index 755528d4..f650e349 100644 --- a/src/server_utils.cpp +++ b/src/server_utils.cpp @@ -67,16 +67,6 @@ void printVariablesHeadersBody(const HTTPRequest &obj) std::cout << c << std::endl; } -void printFrame(std::string frame, bool value) -{ - if (!value) - return; - std::cout << ORANGE << BLINKING; - std::cout << std::setw(10) << ' ' << "***************************" << std::endl; - std::cout << std::setw(10) << ' ' << "* " << frame << " *" << std::endl; - std::cout << std::setw(10) << ' ' << "***************************" << std::endl; - std::cout << RESET; -} void printConnections(const std::string &location, const std::vector &_FDs, diff --git a/src/server_utils.hpp b/src/server_utils.hpp index 7fe71e87..d1ad838c 100644 --- a/src/server_utils.hpp +++ b/src/server_utils.hpp @@ -37,6 +37,5 @@ void printConnections(const std::string &location, const std::vector &_FDs, const std::vector &_connections, bool value); -void printFrame(std::string frame, bool value = false); #endif // SERVER_UTILS_HPP \ No newline at end of file From ea705c979feddf401dec3c6aa36f7d35c7ad366c Mon Sep 17 00:00:00 2001 From: 552020 Date: Fri, 24 May 2024 10:41:57 +0200 Subject: [PATCH 08/13] clean: duplicate log --- src/Server.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Server.cpp b/src/Server.cpp index 13de8a80..9d4ca0f5 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -729,7 +729,6 @@ void Server::acceptNewConnection(Connection &conn) Debug::log("SERVER SOCKET EVENT", Debug::SERVER, CYAN, false, true); struct sockaddr_storage clientAddress; socklen_t ClientAddrLen = sizeof(clientAddress); - Debug::log("New connection detected", Debug::SERVER); int newSocket = accept(conn.getPollFd().fd, (struct sockaddr *)&clientAddress, (socklen_t *)&ClientAddrLen); if (newSocket >= 0) { From f03589f01bba7e45263569ebdf169756ef3551b0 Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 12:43:24 +0200 Subject: [PATCH 09/13] build(openssl): tweak Makefile to install openssl if not present + teak .yml file to install openssl in the ubuntu container running the tests --- .github/workflows/webserv.yml | 4 +-- .gitignore | 1 + Makefile | 42 ++++++++++++++++++------- tests/build/Dockerfile.with-openssl | 23 ++++++++++++++ tests/build/Dockerfile.without-openssl | 23 ++++++++++++++ tests/build/test_build_ubuntu.md | 43 ++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 13 deletions(-) create mode 100644 tests/build/Dockerfile.with-openssl create mode 100644 tests/build/Dockerfile.without-openssl create mode 100644 tests/build/test_build_ubuntu.md diff --git a/.github/workflows/webserv.yml b/.github/workflows/webserv.yml index c62ed509..a0f14bd4 100644 --- a/.github/workflows/webserv.yml +++ b/.github/workflows/webserv.yml @@ -32,6 +32,8 @@ jobs: - name: Check out repository code uses: actions/checkout@v4 - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." + - name: Install necessary dependencies + run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev lsof curl build-sessential - name: List files in the repository run: | ls ${{ github.workspace }} @@ -42,8 +44,6 @@ jobs: python3 -m pip install aiohttp asyncio aiofiles - name: Start webserv in background run: ./webserv & - - name: Install needed dependencies - run: sudo apt-get update && sudo apt-get install -y lsof curl - name: Run Config file tests if: always() working-directory: tests/config diff --git a/.gitignore b/.gitignore index 424f9507..e3e4148c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ # Specific files and directories to include !Makefile !Dockerfile +!Dockerfile.* !.github/ !.clang-format !.vscode/ diff --git a/Makefile b/Makefile index 891e1036..a3312ae8 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ CXX = c++ CXXFLAGS = -Wall -Wextra -Werror -std=c++98 -I. -Iinclude -Isrc -Isrc/events -Isrc/ssl -g DEPFLAGS = -MMD -MP -LDFLAGS = +# -lpthread for pthreads, -ldl for dlopen needed by openssl +LDFLAGS = -lpthread -ldl UNAME_S := $(shell uname -s) # Additional Flags for macOS @@ -14,20 +15,35 @@ endif # Check if pkg-config is available and OpenSSL is installed PKGCONFIG := $(shell which pkg-config) USE_LOCAL_OPENSSL := 0 + ifneq ($(PKGCONFIG),) PKGCONFIG_OPENSSL := $(shell pkg-config --exists openssl && echo 1 || echo 0) - ifeq ($(PKGCONFIG_OPENSSL), 0) - USE_LOCAL_OPENSSL := 1 - else - OPENSSL_INCLUDE := $(shell pkg-config --cflags-only-I openssl | sed 's/-I//') - OPENSSL_LIB := $(shell pkg-config --libs-only-L openssl | sed 's/-L//') - CXXFLAGS += -I$(OPENSSL_INCLUDE) - LDFLAGS += -L$(OPENSSL_LIB) -lssl -lcrypto - endif + ifeq ($(PKGCONFIG_OPENSSL), 1) + OPENSSL_CFLAGS := $(shell pkg-config --cflags openssl) + OPENSSL_LIBS := $(shell pkg-config --libs openssl) + ifneq ($(OPENSSL_CFLAGS),) + CXXFLAGS += $(OPENSSL_CFLAGS) + else + OPENSSL_DIR := $(shell openssl version -d | cut -d'"' -f2) + OPENSSL_INCLUDE := $(OPENSSL_DIR)/include + ifneq ($(wildcard $(OPENSSL_INCLUDE)),) + CXXFLAGS += -I$(OPENSSL_INCLUDE) + endif + endif + LDFLAGS += $(OPENSSL_LIBS) + else + USE_LOCAL_OPENSSL := 1 + endif else USE_LOCAL_OPENSSL := 1 endif +# If using local OpenSSL, update the flags +ifeq ($(USE_LOCAL_OPENSSL), 1) + CXXFLAGS += -I$(LOCAL_INCLUDE) + LDFLAGS += -L$(LOCAL_LIB) -lssl -lcrypto +endif + # Paths for local OpenSSL installation LOCAL_OPENSSL_DIR := $(CURDIR)/local/openssl LOCAL_INCLUDE := $(LOCAL_OPENSSL_DIR)/include @@ -59,6 +75,7 @@ SRCS = src/main.cpp \ src/ssl/SSLContext.cpp OBJDIR = obj OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o) +DEPS = $(OBJS:.o=.d) # Main Target TARGET = webserv @@ -68,7 +85,7 @@ all: check_openssl $(TARGET) # Rule to check and install OpenSSL if needed check_openssl: -ifeq ($(INSTALL_OPENSSL), 1) +ifeq ($(USE_LOCAL_OPENSSL), 1) @echo "OpenSSL not found. Installing locally..." @$(MAKE) install_openssl else @@ -95,16 +112,19 @@ $(OBJDIR)/%.o: %.cpp # Linking the main target $(TARGET): $(OBJS) - $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) + $(CXX) $(OBJS) $(LDFLAGS) -o $(TARGET) # Cleaning up the build clean: rm -rf $(OBJDIR) rm -f $(TARGET) + rm -f $(DEPS) fclean: clean rm -f $(TARGET) re: fclean all +-include $(DEPS) + .PHONY: all clean fclean re check_openssl install_openssl \ No newline at end of file diff --git a/tests/build/Dockerfile.with-openssl b/tests/build/Dockerfile.with-openssl new file mode 100644 index 00000000..8fd29ce0 --- /dev/null +++ b/tests/build/Dockerfile.with-openssl @@ -0,0 +1,23 @@ +# Dockerfile.with-openssl +FROM ubuntu:latest + +# Set environment variables to avoid user prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies including OpenSSL +RUN apt-get update && \ + apt-get install -y build-essential pkg-config openssl libssl-dev wget vim && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Copy project files into the container +COPY . /app + +# Set the working directory +WORKDIR /app + +# Build the project +# RUN make re + +# Set the entrypoint +# ENTRYPOINT ["./webserv"] diff --git a/tests/build/Dockerfile.without-openssl b/tests/build/Dockerfile.without-openssl new file mode 100644 index 00000000..def786e7 --- /dev/null +++ b/tests/build/Dockerfile.without-openssl @@ -0,0 +1,23 @@ +# Dockerfile.with-openssl +FROM ubuntu:latest + +# Set environment variables to avoid user prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies including OpenSSL +RUN apt-get update && \ + apt-get install -y build-essential pkg-config wget libpthread-stubs0-dev libdl-dev vim && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Copy project files into the container +COPY . /app + +# Set the working directory +WORKDIR /app + +# Build the project +# RUN make re + +# Set the entrypoint +# ENTRYPOINT ["./webserv"] diff --git a/tests/build/test_build_ubuntu.md b/tests/build/test_build_ubuntu.md new file mode 100644 index 00000000..e8ade912 --- /dev/null +++ b/tests/build/test_build_ubuntu.md @@ -0,0 +1,43 @@ +# Testing Build with Docker + +This document provides instructions to build and run Docker images for testing the project with and without OpenSSL installed. + +## Building Docker Images + +### Build Image with OpenSSL Installed + +From the root of the repository: + +```sh +docker build -f tests/build/Dockerfile.with-openssl -t ubuntu-with-openssl . +``` + +### Build Image without OpenSSL Installed + +From the root of the repository: + +```sh +docker build -f tests/build/Dockerfile.without-openssl -t ubuntu-without-openssl . +``` + +## Running the Docker Images + +### Run the Image with OpenSSL Installed + +To run the Docker container with OpenSSL installed in interactive mode, use the following command: + +```sh +docker run --rm -it ubuntu-with-openssl +``` + +### Run the Image without OpenSSL Installed + +To run the Docker container without OpenSSL installed in interactive mode, use the following command: + +```sh +docker run --rm -it ubuntu-without-openssl +``` + +## Test the build + +`Make re` and check what happens. From f8f881a1a1750152ca5382305c653798a49389f6 Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 12:45:14 +0200 Subject: [PATCH 10/13] build(openssl): correct typo --- .github/workflows/webserv.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/webserv.yml b/.github/workflows/webserv.yml index a0f14bd4..077c1338 100644 --- a/.github/workflows/webserv.yml +++ b/.github/workflows/webserv.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v4 - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner." - name: Install necessary dependencies - run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev lsof curl build-sessential + run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev lsof curl build-essential - name: List files in the repository run: | ls ${{ github.workspace }} From bf47ba36a67ffaa9b02382f95551e850c16af373 Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 13:37:19 +0200 Subject: [PATCH 11/13] clean: remove all the print behind VERBOSE, and the VERBOSE macro --- src/Server.cpp | 44 +------------------------------------------- src/Server.hpp | 4 +--- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/src/Server.cpp b/src/Server.cpp index b261f994..77b43531 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -709,32 +709,13 @@ void Server::addServerSocketsPollFdToVectors() serverPollFd.fd = it->getServerFD(); serverPollFd.events = POLLIN; serverPollFd.revents = 0; - if (VERBOSE) - { - std::cout << "pollfd struct for Server socket created" << std::endl; - std::cout << std::endl; - std::cout << "Printing serverPollFd (struct pollfd) before push_back into _FDs" << std::endl; - std::cout << "fd: " << serverPollFd.fd << ", events: " << serverPollFd.events - << ", revents: " << serverPollFd.revents << std::endl; - } _FDs.push_back(serverPollFd); + Connection serverConnection(serverPollFd, *this); serverConnection.setType(SERVER); serverConnection.setServerIp(it->getListen().getIp()); serverConnection.setServerPort(it->getListen().getPort()); - if (VERBOSE) - { - std::cout << "Server Connection object created" << std::endl; - std::cout << MAGENTA << "Printing serverConnection before push_back" << std::endl << RESET; - serverConnection.printConnection(); - } _connections.push_back(serverConnection); - if (VERBOSE) - { - std::cout << MAGENTA << "Printing serverConnection after push_back" << RESET << std::endl; - _connections.back().printConnection(); - std::cout << "Server socket pollfd added to vectors" << std::endl; - } } } @@ -754,40 +735,17 @@ void Server::acceptNewConnection(Connection &conn) Connection newConnection(newSocketPoll, *this); newConnection.setType(CLIENT); newConnection.setServerIp(conn.getServerIp()); - if (_connectionsPerIP.find(conn.getServerIp()) == _connectionsPerIP.end()) _connectionsPerIP.insert(std::pair(conn.getServerIp(), 1)); else _connectionsPerIP[conn.getServerIp()] += 1; newConnection.setServerPort(conn.getServerPort()); - if (VERBOSE) - { - - std::cout << PURPLE << "BEFORE PUSH_BACK" << RESET << std::endl; - std::cout << "Printing newConnection:" << std::endl; - newConnection.printConnection(); - std::cout << "Printing struct pollfd newSocketPoll:" << std::endl; - std::cout << "fd: " << newSocketPoll.fd << ", events: " << newSocketPoll.events - << ", revents: " << newSocketPoll.revents << std::endl; - } /* start together */ _FDs.push_back(newSocketPoll); _connections.push_back(newConnection); ++_clientCounter; /* end together */ - if (VERBOSE) - { - std::cout << PURPLE << "AFTER PUSH_BACK" << RESET << std::endl; - std::cout << "Printing last element of _FDs:" << std::endl; - std::cout << "fd: " << _FDs.back().fd << ", events: " << _FDs.back().events - << ", revents: " << _FDs.back().revents << std::endl; - std::cout << "Printing last element of _connections:" << std::endl; - _connections.back().printConnection(); - std::cout << "Pringing the whole _FDs and _connections vectors after adding new connection" << std::endl; - print_connectionsVector(_connections); - printFDsVector(_FDs); - } char clientIP[INET6_ADDRSTRLEN]; if (clientAddress.ss_family == AF_INET) { diff --git a/src/Server.hpp b/src/Server.hpp index 38db2e35..844e6024 100644 --- a/src/Server.hpp +++ b/src/Server.hpp @@ -21,8 +21,6 @@ #include "ServerSocket.hpp" #include "EventManager.hpp" -#define VERBOSE 0 - class Connection; // Forward declaration for circular dependencyA class Server @@ -33,7 +31,7 @@ class Server void startListening(); void startPollEventLoop(); - + void printServerSockets() const; /* for CGI */ void setHasCGI(bool hasCGI); From 9762a58e8fb0132f4e209c08219e5d70285b3fda Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 14:46:45 +0200 Subject: [PATCH 12/13] docs: add doc about ssl struct from openssl --- docs/SSL/ssl.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/SSL/ssl.md diff --git a/docs/SSL/ssl.md b/docs/SSL/ssl.md new file mode 100644 index 00000000..f362459a --- /dev/null +++ b/docs/SSL/ssl.md @@ -0,0 +1,120 @@ +### SSL Object (or SSL Structure) + +The `SSL` object in OpenSSL represents a single SSL/TLS connection. It encapsulates all the data and state needed to manage an SSL/TLS session between a client and a server. + +### Key Functions of the SSL Object + +1. **Manage SSL/TLS Sessions**: + + - Handles the SSL/TLS handshake, which establishes the encryption parameters and authenticates the connection. + - Manages the session state, including encryption keys, certificates, and negotiated parameters. + +2. **Data Encryption and Decryption**: + + - Encrypts data sent over the connection, ensuring privacy and data integrity. + - Decrypts incoming data, making it readable for the application. + +3. **Communication**: + - Provides functions for reading and writing encrypted data (`SSL_read`, `SSL_write`). + - Handles underlying network communication securely. + +### Common Operations with the SSL Object + +- **Creation**: An `SSL` object is created using `SSL_new(SSL_CTX *ctx)`, where `ctx` is the SSL context that defines configuration and parameters for the connection. + + ```c + SSL *ssl = SSL_new(SSL_CTX *ctx); + ``` + + Creates a new `SSL` object from the given context. + +- **Association with Socket**: The `SSL` object is associated with a network socket using `SSL_set_fd(SSL *ssl, int fd)`, linking the SSL session to a specific socket file descriptor. + + ```c + SSL_set_fd(SSL *ssl, int fd); + ``` + + Associates the `SSL` object with a network socket. + +- **Handshake**: The SSL/TLS handshake is initiated using `SSL_accept` (for servers) or `SSL_connect` (for clients). This step negotiates the SSL/TLS parameters and establishes a secure connection. + + ```c + int result = SSL_accept(SSL *ssl); // For servers + int result = SSL_connect(SSL *ssl); // For clients + ``` + + Performs the SSL/TLS handshake. + +- **Data Transfer**: Secure data transfer is performed using `SSL_read` to receive data and `SSL_write` to send data. + + ```c + int bytes = SSL_read(SSL *ssl, void *buf, int num); + int bytes = SSL_write(SSL *ssl, const void *buf, int num); + ``` + + Reads and writes encrypted data. + +- **Shutdown**: The SSL connection is properly closed using `SSL_shutdown` to ensure all encrypted data is properly transmitted and received before the connection is terminated. + + ```c + int result = SSL_shutdown(SSL *ssl); + ``` + + Properly shuts down the SSL connection. + +- **Cleanup**: When the connection is no longer needed, `SSL_free` is called to free the `SSL` object and release associated resources. + + ```c + SSL_free(SSL *ssl); + ``` + + Frees the `SSL` object and associated resources. + +### Structure of the SSL Object + +The `SSL` object in OpenSSL is a structure. Here is a partial definition to give you an idea of its components. For the complete structure, refer to the OpenSSL source code. + +```c +struct ssl_st { + // SSL session information + SSL_CTX *ctx; + // Underlying BIOs for network communication + BIO *rbio; /* used by SSL_read */ + BIO *wbio; /* used by SSL_write */ + BIO *bbio; /* used during session-id reuse to concatenate messages */ + + // SSL connection state + int state; + int rwstate; + int in_handshake; + int server; /* are we the server side? - mostly used by SSL_clear */ + int new_session; /* flag to indicate a new session */ + int quiet_shutdown; + int shutdown; /* we have shut things down, 0x01 sent, 0x02 for received */ + int init_num; /* number of bytes in init_buf */ + int init_off; /* offset into init_buf */ + // and many more... +}; +``` + +### Example + +```cpp +SSL *ssl = SSL_new(ctx); // Create a new SSL object +SSL_set_fd(ssl, socket_fd); // Associate the SSL object with a socket +if (SSL_accept(ssl) <= 0) { // Perform the SSL handshake + // Handle error +} +SSL_write(ssl, data, data_len); // Send encrypted data +SSL_read(ssl, buffer, buf_len); // Receive encrypted data +SSL_shutdown(ssl); // Properly close the SSL connection +SSL_free(ssl); // Free the SSL object and resources +``` + +## Further Information + +For detailed information on the `SSL` object and related functions, refer to the following resources: + +- [OpenSSL Documentation](https://www.openssl.org/docs/) +- [OpenSSL `SSL` Object Manual](https://www.openssl.org/docs/man1.1.1/man3/SSL_new.html) +- [OpenSSL Source Code](https://github.com/openssl/openssl) (particularly the `ssl/ssl.h` file) From 58bd4cb5d10da2c44f1b300e151e9f75ed589629 Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 15:07:40 +0200 Subject: [PATCH 13/13] feat(SSL): move SSLManager singleton and SSLContext into the Server and add logic to acceptNewConnection to create a ssl struct for the connection and pass it to the Connection object on initialisation --- src/Connection.cpp | 27 +++++++++++++++++++++++- src/Connection.hpp | 10 ++++++++- src/Server.cpp | 52 +++++++++++++++++++++++++++++++++++++++------- src/Server.hpp | 7 +++++++ src/main.cpp | 6 ++---- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/Connection.cpp b/src/Connection.cpp index 9b2473b3..fc4f17b6 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -1,6 +1,6 @@ #include "Connection.hpp" -Connection::Connection(struct pollfd &pollFd, Server &server) +Connection::Connection(struct pollfd &pollFd, Server &server, SSL *ssl) { (void)server; @@ -28,6 +28,8 @@ Connection::Connection(struct pollfd &pollFd, Server &server) _CGIHasTimedOut = false; _CGIHasReadPipe = false; _startTime = 0; + _ssl = ssl; + _isSSL = ssl != NULL; } Connection::Connection(const Connection &other) @@ -61,6 +63,8 @@ Connection::Connection(const Connection &other) _CGIHasReadPipe = other._CGIHasReadPipe; _cgiOutputBuffer = other._cgiOutputBuffer; _startTime = other._startTime; + _ssl = other._ssl; + _isSSL = other._isSSL; // std::cout << "Connection object copied" << std::endl; } @@ -95,6 +99,8 @@ Connection &Connection::operator=(const Connection &other) _CGIHasReadPipe = other._CGIHasReadPipe; _cgiOutputBuffer = other._cgiOutputBuffer; _startTime = other._startTime; + _ssl = other._ssl; + _isSSL = other._isSSL; } Debug::log("Connection object assigned", Debug::OCF); return *this; @@ -242,6 +248,16 @@ time_t Connection::getStartTime() const return _startTime; } +bool Connection::getIsSSL() const +{ + return _isSSL; +} + +SSL *Connection::getSSL() const +{ + return _ssl; +} + // SETTERS void Connection::setStartTime(time_t time) @@ -348,6 +364,15 @@ void Connection::setCGIExitStatus(int status) _CGIExitStatus = status; } +void Connection::setIsSSL(bool value) +{ + _isSSL = value; +} + +void Connection::setSSL(SSL *ssl) +{ + _ssl = ssl; +} // METHODS ssize_t Connection::readSocket(char *buffer, size_t bufferSize) diff --git a/src/Connection.hpp b/src/Connection.hpp index 3fd19022..1d3c393d 100644 --- a/src/Connection.hpp +++ b/src/Connection.hpp @@ -59,8 +59,12 @@ class Connection bool _CGIHasReadPipe; std::string _cgiOutputBuffer; + /* SSL */ + SSL *_ssl; + bool _isSSL; + public: - Connection(struct pollfd &pollFd, Server &server); + Connection(struct pollfd &pollFd, Server &server, SSL *ssl = NULL); Connection(const Connection &other); Connection &operator=(const Connection &other); ~Connection(); @@ -105,6 +109,8 @@ class Connection bool getCGIHasTimedOut() const; bool getCGIHasReadPipe() const; std::string getCGIOutputBuffer() const; + SSL *getSSL() const; + bool getIsSSL() const; /* Setters */ void setResponseString(std::string responseString); @@ -131,6 +137,8 @@ class Connection void setCGIHasTimedOut(bool value); void setCGIHasReadPipe(bool value); void setCGIOutputBuffer(std::string output); + void setSSL(SSL *ssl); + void setIsSSL(bool isSSL); /* CGI */ void addCGI(pid_t pid); void removeCGI(int status); diff --git a/src/Server.cpp b/src/Server.cpp index 77b43531..ff660a27 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -6,6 +6,8 @@ #include "EventManager.hpp" #include "signal.h" +#define SSL_PORT 8443 + Server::Server(const Config &config, EventManager &eventManager) : _config(config), _eventManager(eventManager) { _maxClients = 10; @@ -15,6 +17,8 @@ Server::Server(const Config &config, EventManager &eventManager) : _config(confi _hasCGI = false; _CGICounter = 0; _clientCounter = 0; + _sslManager = SSLManager::getInstance(); + _sslContext = SSLContext(); Debug::log("Server created with config constructor", Debug::OCF); } @@ -481,7 +485,15 @@ void Server::closeClientConnection(Connection &conn, size_t &i) << "Entering closeClientConnection" << "\033[0m" << std::endl; // TODO: should we close it with the Destructor of the Connection class? + if (conn.getIsSSL() && conn.getSSL() != NULL) + { + SSL_shutdown(conn.getSSL()); + SSL_free(conn.getSSL()); + conn.setSSL(NULL); + conn.setIsSSL(false); + } close(conn.getPollFd().fd); + _FDs.erase(_FDs.begin() + i); _connections.erase(_connections.begin() + i); _connectionsPerIP[conn.getServerIp()] -= 1; @@ -719,28 +731,52 @@ void Server::addServerSocketsPollFdToVectors() } } -void Server::acceptNewConnection(Connection &conn) +void Server::acceptNewConnection(Connection &serverConn) { Debug::log("SERVER SOCKET EVENT", Debug::SERVER, CYAN, false, true); struct sockaddr_storage clientAddress; socklen_t ClientAddrLen = sizeof(clientAddress); - int newSocket = accept(conn.getPollFd().fd, (struct sockaddr *)&clientAddress, (socklen_t *)&ClientAddrLen); + int newSocket = accept(serverConn.getPollFd().fd, (struct sockaddr *)&clientAddress, (socklen_t *)&ClientAddrLen); if (newSocket >= 0) { struct pollfd newSocketPoll; newSocketPoll.fd = newSocket; newSocketPoll.events = POLLIN; newSocketPoll.revents = 0; - Connection newConnection(newSocketPoll, *this); + // Before we create a new connection object, we set up the connection as SSL or not + SSL *ssl = NULL; + if (serverConn.getServerPort() == SSL_PORT) + { + // We create a new SSL object + ssl = SSL_new(_sslContext.getContext()); + if (ssl == NULL) + { + Debug::log("Error creating SSL object", Debug::SERVER); + perror("In SSL_new"); + close(newSocket); + return; + } + SSL_set_fd(ssl, newSocket); + if (SSL_accept(ssl) <= 0) + { + Debug::log("Error accepting SSL connection", Debug::SERVER); + perror("In SSL_accept"); + SSL_free(ssl); + close(newSocket); + return; + } + // We set the SSL object to the connection + } + Connection newConnection(newSocketPoll, *this, ssl); newConnection.setType(CLIENT); - newConnection.setServerIp(conn.getServerIp()); - if (_connectionsPerIP.find(conn.getServerIp()) == _connectionsPerIP.end()) - _connectionsPerIP.insert(std::pair(conn.getServerIp(), 1)); + newConnection.setServerIp(serverConn.getServerIp()); + if (_connectionsPerIP.find(serverConn.getServerIp()) == _connectionsPerIP.end()) + _connectionsPerIP.insert(std::pair(serverConn.getServerIp(), 1)); else - _connectionsPerIP[conn.getServerIp()] += 1; + _connectionsPerIP[serverConn.getServerIp()] += 1; - newConnection.setServerPort(conn.getServerPort()); + newConnection.setServerPort(serverConn.getServerPort()); /* start together */ _FDs.push_back(newSocketPoll); _connections.push_back(newConnection); diff --git a/src/Server.hpp b/src/Server.hpp index 844e6024..6749b7da 100644 --- a/src/Server.hpp +++ b/src/Server.hpp @@ -19,6 +19,8 @@ #include "Parser.hpp" #include "Config.hpp" #include "ServerSocket.hpp" +#include "SSLContext.hpp" +#include "SSLManager.hpp" #include "EventManager.hpp" class Connection; // Forward declaration for circular dependencyA @@ -65,6 +67,11 @@ class Server int _CGICounter; // number of connections per IP std::map _connectionsPerIP; + // SSL manager and context + // It is a pointer cause we want to use the singleton pattern + SSLManager *_sslManager; + // Normal object + SSLContext _sslContext; /*** Private Methods ***/ Server(); diff --git a/src/main.cpp b/src/main.cpp index f0d3a4c3..75a5217f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,10 +29,8 @@ int main(int argc, char **argv) eventManager.subscribe(&serverEventListener); // Initialize SSLManager and SSLContext - SSLManager *sslManager = SSLManager::getInstance(); - (void)sslManager; - SSLContext sslContext; - (void)sslContext; + // SSLManager *sslManager = SSLManager::getInstance(); + // SSLContext sslContext; webserv.startListening(); webserv.startPollEventLoop();