From 58bd4cb5d10da2c44f1b300e151e9f75ed589629 Mon Sep 17 00:00:00 2001 From: 552020 Date: Sun, 26 May 2024 15:07:40 +0200 Subject: [PATCH] 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 9b2473b..fc4f17b 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 3fd1902..1d3c393 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 77b4353..ff660a2 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 844e602..6749b7d 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 f0d3a4c..75a5217 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();