#include "Server.h" #include #include #ifndef WIN32 # include #endif #include #include #include #include using namespace Network; // Inhalt der Server Klasse aus Server.h // Konstruktor Server::Server() : ReferenceCounter() { sock = 0; memset(&addresse, 0, sizeof(addresse)); // Adresse setzen addresse.sin_family = AF_INET; addresse.sin_addr.s_addr = ADDR_ANY; klients = 0; } // Destruktor Server::~Server() { trenne(); } // nicht constant bool Server::verbinde( unsigned short port, int warteschlangenLen) // Öffnet das Socket { sock = socket(AF_INET, SOCK_STREAM, 0); // Socket erstellen addresse.sin_port = htons(port); // port setzen if (sock < 0) { sock = 0; return 0; } #ifdef WIN32 char reuseSocket = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(char)); #else int reuseSocket = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(int)); #endif if (bind(sock, (struct sockaddr*)&addresse, sizeof(addresse)) == -1) // socket öffnen { trenne(); return 0; // Fehler } if (listen(sock, warteschlangenLen) == -1) // Klients annehmen { trenne(); return 0; // Fehler } return 1; } SKlient* Server::getKlient() // nimmt Klient an { if (!sock) return 0; sockaddr_in client; int len = sizeof(addresse); fd_set set; int rv = 0; struct timeval timeout; while (rv == 0 && sock) { FD_ZERO(&set); /* clear the set */ FD_SET(sock, &set); /* add our file descriptor to the set */ timeout.tv_sec = 10; timeout.tv_usec = 0; rv = select((int)sock + 1, &set, NULL, NULL, &timeout); if (rv == -1) return 0; } if (!sock) return 0; #ifdef WIN32 SOCKET cls = accept(sock, (sockaddr*)&client, &len); // Klient empfangen if (cls == INVALID_SOCKET) { trenne(); return 0; } #else SOCKET cls = accept( sock, (sockaddr*)&client, (socklen_t*)&len); // Klient empfangen if (!cls) { if (errno == ECONNABORTED || errno == EBADF) trenne(); return 0; } #endif client.sin_port = addresse.sin_port; klients++; return new SKlient(client, cls); // Klient Handle Klasse zurückgeben } int Server::getKlients(bool reset) // gibt die Anzahl der Klients zurück { int ret = klients; if (reset) klients = 0; return ret; } bool Server::trenne() // beendet den Server { if (!sock) return 1; if (closesocket(sock) < 0) // socket schließen return 0; sock = 0; return 1; } // constant unsigned short Server::getPort() const // gibt den Port zurück { return htons(addresse.sin_port); } bool Server::isConnected() const // giebt 1 zurück, falls der Server verbunden ist { return sock != 0; } // Inhalt der SKlient Klasse aus Server.h // Konstruktor SKlient::SKlient(sockaddr_in addresse, SOCKET sock) : ReferenceCounter() { clientAddr = addresse; this->sock = sock; downStreamBytes = 0; upStreamBytes = 0; sendeKey = 0; empfangKey = 0; } // Destruktor SKlient::~SKlient() { trenne(); if (sendeKey) sendeKey->release(); if (empfangKey) empfangKey->release(); } // nicht constant void SKlient::setEmpfangTimeout( int miliseconds) // Setzt ein timeout fürs empfangen von daten { #ifdef WIN32 DWORD timeout = miliseconds; setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); #else struct timeval tv; tv.tv_sec = miliseconds / 1000; tv.tv_usec = (miliseconds % 1000) * 1000; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); #endif } void SKlient::setSendeKeyZ(Encryption::Key* key) // Setzt den Key fürs Senden { if (sendeKey) sendeKey->release(); sendeKey = key; } void SKlient::setEmpfangKeyZ( Encryption::Key* key) // Setzt den Key fürs Empfangen { if (empfangKey) empfangKey->release(); empfangKey = key; } void SKlient::setSendeKey(const char* key, int len) // Setzt den Key fürs Senden { if (!sendeKey) sendeKey = new Encryption::Key(); sendeKey->setKey(key, len); } void SKlient::setEmpfangKey( const char* key, int len) // Setzt den Key fürs Empfangen { if (!empfangKey) empfangKey = new Encryption::Key(); empfangKey->setKey(key, len); } bool SKlient::sende(const char* nachricht, int len) // sendet zum Klient { if (!sock) return 0; int ll = 0; while (len > 0) { #ifdef WIN32 int l = send(sock, nachricht + ll, len, 0); #else int l = (int)send(sock, nachricht + ll, len, MSG_NOSIGNAL); #endif if (l <= 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "send: " << l << " Error: " << WSAGetLastError(); # endif #endif return 0; // Fehler } len -= l; ll += l; } upStreamBytes += ll; return 1; } bool SKlient::getNachricht( char* nachricht, int len) // empfängt Nachricht von Klient { if (!sock) return 0; int ll = 0; while (len > 0) { int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL); if (l <= 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "recv: " << l << " Error: " << WSAGetLastError(); # endif #endif return 0; // Fehler } len -= l; ll += l; } downStreamBytes += ll; return 1; } bool SKlient::sendeEncrypted( const char* nachricht, int len) // sendet zum Server { if (!sendeKey) return sende(nachricht, len); Encryption::Bytes* n = new Encryption::Bytes(nachricht, len); sendeKey->codieren(dynamic_cast(n->getThis())); int ll = 0; while (len > 0) { #ifdef WIN32 int l = send(sock, n->getBytes() + ll, len, 0); #else int l = (int)send(sock, n->getBytes() + ll, len, MSG_NOSIGNAL); #endif if (l <= 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "send: " << l << " Error: " << WSAGetLastError(); # endif #endif n->release(); return 0; // Fehler } len -= l; ll += l; } upStreamBytes += ll; n->release(); return 1; } bool SKlient::getNachrichtEncrypted( char* nachricht, int len) // empfängt Nachricht { if (!empfangKey) return getNachricht(nachricht, len); int ll = 0; while (len > 0) { int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL); if (l <= 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "recv: " << l << " Error: " << WSAGetLastError(); # endif #endif return 0; // Fehler } len -= l; ll += l; } Encryption::Bytes* n = new Encryption::Bytes(); n->setBytesZ(nachricht, ll); empfangKey->decodieren(n); downStreamBytes += ll; return 1; } int SKlient::getDownloadBytes( bool reset) // gibt die anzahl von empfangen bytes zurück { int ret = downStreamBytes; if (reset) downStreamBytes = 0; return ret; } int SKlient::getUploadBytes( bool reset) // gibt die anzahl von versendeter bytes zurück { int ret = upStreamBytes; if (reset) upStreamBytes = 0; return ret; } bool SKlient::trenne() // trennt die Verbindung zum Klient { if (!sock) return 0; if (closesocket(sock) < 0) // trennen return 0; sock = 0; return 1; } // constant bool SKlient::hatNachricht( int zeit) const // Wartet eine Zeit Lang auf eine Nachricht { fd_set set; FD_ZERO(&set); FD_SET(sock, &set); timeval time = {zeit / 1000, zeit}; int result = select(0, &set, 0, 0, &time); if (result < 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "select: " << result << " Error: " << WSAGetLastError(); # endif #endif } return result > 0; } unsigned short SKlient::getPort() const // gibt den Port zurück { return htons(clientAddr.sin_port); } const char* SKlient::getIp() const // gibt die Ip des Klients zurück { return inet_ntoa(clientAddr.sin_addr); } int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata) { const char* passw = ((Text*)userdata)->getText(); memcpy(buf, passw, MIN((unsigned int)size, strlen(passw) + 1)); return (int)strlen(buf); } bool SSLErrorCheck(int result, SSL* ssl, const char* action) { if (result <= 0) { Framework::Logging::error() << "'" << action << "' returned error code: " << SSL_get_error(ssl, result); return 0; } return 1; } bool SSLErrorCheck(__int64 result, const char* action) { if (result <= 0) { unsigned long error = ERR_get_error(); Framework::Logging::error() << "'" << action << "' returned " << result << " error code: " << error << "(" << ERR_reason_error_string(error) << ")"; return 0; } return 1; } bool SKlient::waitForNextMessage() const // wartet bis es etwas zu empfangen gibt { fd_set set; int rv = 0; struct timeval timeout; while (rv == 0 && sock) { FD_ZERO(&set); /* clear the set */ FD_SET(sock, &set); /* add our file descriptor to the set */ timeout.tv_sec = 10; timeout.tv_usec = 0; rv = select((int)sock + 1, &set, NULL, NULL, &timeout); if (rv == -1) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "select: " << rv << " Error: " << WSAGetLastError(); # endif #endif return 0; } } if (!sock) return 0; char c; #ifdef WIN32 int l = (int)recv(sock, &c, 1, MSG_PEEK); #else int l = (int)recv(sock, &c, 1, MSG_WAITALL | MSG_PEEK); #endif if (l <= 0) { #ifdef WIN32 # ifdef _DEBUG Framework::Logging::warning() << "recv: " << l << " Error: " << WSAGetLastError(); # endif #endif return 0; // Fehler } return 1; } // Inhalt der SSLServer Klasse // Konstruktor SSLServer::SSLServer() : ReferenceCounter() { s = 0; const SSL_METHOD* method = TLS_server_method(); ctx = SSL_CTX_new(method); SSLErrorCheck(SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION), "SSL_CTX_set_min_proto_version"); SSLErrorCheck(SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION), "SSL_CTX_set_max_proto_version"); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); passw = new Text(); SSL_CTX_set_default_passwd_cb_userdata(ctx, passw); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); klients = 0; } // Destruktor SSLServer::~SSLServer() { trenne(); SSL_CTX_free(ctx); passw->release(); #ifdef WIN32 OPENSSL_thread_stop(); #endif } // nicht constant // Setzt den Pfad zur Datei, in dem das Certifikat gespeichert ist bool SSLServer::setCertificateFile(const char* file) { return SSLErrorCheck( SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM), "SSL_CTX_use_certificate_file"); } // Setzt den Pfad zur Datei, in dem der private Schlüssel gespeichert ist bool SSLServer::setPrivateKeyFile(const char* file) { return SSLErrorCheck( SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM), "SSL_CTX_use_PrivateKey_file"); } // setzt das passwort des private keys (muss vor setPrivateKeyFile aufgerufen // werden) void SSLServer::setPrivateKeyPassword(const char* password) { passw->setText(password); } // Öffnet das Socket bool SSLServer::verbinde(unsigned short port, int warteschlangenLen) { addr.sin_port = htons(port); s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { s = 0; return 0; } #ifdef WIN32 char reuseSocket = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(char)); #else int reuseSocket = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(int)); #endif if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { trenne(); return 0; } if (listen(s, warteschlangenLen) < 0) { trenne(); return 0; } return 1; } // nimmt Klient an SSLSKlient* SSLServer::getKlient() { if (!s) return 0; int len = sizeof(addr); struct sockaddr_in addr; fd_set set; int rv = 0; struct timeval timeout; while (rv == 0 && s) { FD_ZERO(&set); /* clear the set */ FD_SET(s, &set); /* add our file descriptor to the set */ timeout.tv_sec = 10; timeout.tv_usec = 0; rv = select((int)s + 1, &set, NULL, NULL, &timeout); if (rv == -1) return 0; } if (!s) return 0; #ifdef WIN32 SOCKET client = accept(s, (struct sockaddr*)&addr, &len); if (client == INVALID_SOCKET) { trenne(); return 0; } #else SOCKET client = accept(s, (sockaddr*)&addr, (socklen_t*)&len); // Klient empfangen if (!client) { if (errno == ECONNABORTED || errno == EBADF) trenne(); return 0; } #endif addr.sin_port = this->addr.sin_port; SSL* ssl = SSL_new(ctx); if (ssl == 0 && !SSLErrorCheck(0, "SSL_new")) { closesocket(client); return 0; } if (!SSLErrorCheck(SSL_set_fd(ssl, (int)client), ssl, "SSL_set_fd")) { SSL_free(ssl); closesocket(client); return 0; } if (!SSLErrorCheck(SSL_accept(ssl), ssl, "SSL_accept")) { SSL_free(ssl); closesocket(client); return 0; } klients++; return new SSLSKlient(addr, ssl, client); } // gibt die Anzahl der Klients zurück int SSLServer::getKlients(bool reset) { int ret = klients; if (reset) klients = 0; return ret; } // beendet den Server bool SSLServer::trenne() { if (!s) return 1; if (closesocket(s) < 0) // socket schließen return 0; s = 0; return 1; } // constant // gibt den Port zurück unsigned short SSLServer::getPort() const { return htons(addr.sin_port); } // giebt 1 zurück, falls der Server verbunden ist bool SSLServer::isConnected() const { return s != 0; } // Inhalt der SSLSKlient Klasse // Konstruktor SSLSKlient::SSLSKlient(sockaddr_in client, SSL* ssl, SOCKET s) : ReferenceCounter() { this->s = s; clientAddr = client; this->ssl = ssl; downStreamBytes = 0; upStreamBytes = 0; } // Destruktor SSLSKlient::~SSLSKlient() { trenne(); #ifdef WIN32 OPENSSL_thread_stop(); #endif } // nicht constant void SSLSKlient::setEmpfangTimeout( int miliseconds) // Setzt ein timeout fürs empfangen von daten { #ifdef WIN32 DWORD timeout = miliseconds; setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); #else struct timeval tv; tv.tv_sec = miliseconds / 1000; tv.tv_usec = (miliseconds % 1000) * 1000; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); #endif } bool SSLSKlient::sende(const char* nachricht, int len) // sendet zum Klient { if (!ssl) return 0; int ll = 0; while (len > 0) { int l = SSL_write(ssl, nachricht + ll, len); if (l <= 0) { #ifdef _DEBUG Framework::Logging::warning() << "SSL_write: " << l << " Error: " << SSL_get_error(ssl, l); #endif return 0; // Fehler } len -= l; ll += l; } upStreamBytes += ll; return 1; } bool SSLSKlient::getNachricht( char* nachricht, int len) // empfängt Nachricht von Klient { if (!ssl) return 0; int ll = 0; while (len > 0) { int l = (int)SSL_read(ssl, nachricht + ll, len); if (l <= 0) { #ifdef _DEBUG Framework::Logging::warning() << "SSL_read: " << l << " Error: " << SSL_get_error(ssl, l); #endif return 0; // Fehler } len -= l; ll += l; } downStreamBytes += ll; return 1; } int SSLSKlient::getDownloadBytes( bool reset) // gibt die anzahl von empfangen bytes zurück { int ret = downStreamBytes; if (reset) downStreamBytes = 0; return ret; } int SSLSKlient::getUploadBytes( bool reset) // gibt die anzahl von versendeter bytes zurück { int ret = upStreamBytes; if (reset) upStreamBytes = 0; return ret; } bool SSLSKlient::trenne() // trennt die Verbindung zum Klient { if (!ssl) return 0; SSL_free(ssl); if (closesocket(s) < 0) // trennen return 0; ssl = 0; s = 0; return 1; } // constant bool SSLSKlient::hatNachricht( int zeit) const // Wartet eine Zeit Lang auf eine Nachricht { fd_set set; FD_ZERO(&set); FD_SET(SSL_get_rfd(ssl), &set); timeval time = {zeit / 1000, zeit}; return SSL_pending(ssl) > 0 || select(0, &set, 0, 0, &time) == 1; } unsigned short SSLSKlient::getPort() const // gibt den Port zurück { return htons(clientAddr.sin_port); } const char* SSLSKlient::getIp() const // gibt die Ip des Klients zurück { return inet_ntoa(clientAddr.sin_addr); }