#include #include #include "Server.h" #ifndef WIN32 #include #endif #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( 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 ); #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( char* key, int len ) // Setzt den Key fürs Senden { if( !sendeKey ) sendeKey = new Encryption::Key(); sendeKey->setKey( key, len ); } void SKlient::setEmpfangKey( 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 ) 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 ) 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 ) { 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 ) 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 }; return select( 0, &set, 0, 0, &time ) == 1; } 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 ) { std::cout << "ERROR: '" << action << "' returned error code: " << SSL_get_error( ssl, result ) << "\n"; std::cout.flush(); return 0; } return 1; } bool SSLErrorCheck( __int64 result, const char* action ) { if( result <= 0 ) { unsigned long error = ERR_get_error(); std::cout << "ERROR: '" << action << "' returned " << result << " error code: " << error << "(" << ERR_reason_error_string( error ) << ")\n"; std::cout.flush(); return 0; } return 1; } bool SKlient::waitForNextMessage() const // wartet bis es etwas zu empfangen gibt { char c; int l = (int)recv( sock, &c, 1, MSG_WAITALL | MSG_PEEK ); if( l <= 0 ) 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; } 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; #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 ) 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 ) 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 ); }