#include #include "Server.h" #ifndef WIN32 #include #endif #include #include using namespace Network; // Inhalt der Server Klasse aus Server.h // Konstruktor Server::Server() { sock = 0; memset( &addresse, 0, sizeof( addresse ) ); // Adresse setzen addresse.sin_family = AF_INET; addresse.sin_addr.s_addr = ADDR_ANY; ref = 1; 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; } // Reference Counting Server *Server::getThis() { ref++; return this; } Server *Server::release() { ref--; if( !ref ) delete this; return 0; } // Inhalt der SKlient Klasse aus Server.h // Konstruktor SKlient::SKlient( sockaddr_in addresse, SOCKET sock ) { clientAddr = addresse; this->sock = sock; ref = 1; downStreamBytes = 0; upStreamBytes = 0; sendeKey = 0; empfangKey = 0; } // Destruktor SKlient::~SKlient() { trenne(); if( sendeKey ) sendeKey->release(); if( empfangKey ) empfangKey->release(); } // nicht constant 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( 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 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 ); } // Reference Counting SKlient *SKlient::getThis() { ref++; return this; } SKlient *SKlient::release() { ref--; if( !ref ) delete this; return 0; } 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 ); } // Inhalt der SSLServer Klasse // Konstruktor SSLServer::SSLServer() { s = 0; ctx = SSL_CTX_new( SSLv23_server_method() ); 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; ref = 1; } // 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 SSL_CTX_use_certificate_file( ctx, file, SSL_FILETYPE_PEM ) > 0; } // Setzt den Pfad zur Datei, in dem der private Schlüssel gespeichert ist bool SSLServer::setPrivateKeyFile( const char *file ) { return SSL_CTX_use_PrivateKey_file( ctx, file, SSL_FILETYPE_PEM ) > 0; } // 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 ); SSL_set_fd( ssl, (int)client ); if( SSL_accept( ssl ) <= 0 ) { 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; } // Reference Counting SSLServer *SSLServer::getThis() { ref++; return this; } SSLServer *SSLServer::release() { if( !--ref ) delete this; return 0; } // Inhalt der SSLSKlient Klasse // Konstruktor SSLSKlient::SSLSKlient( sockaddr_in client, SSL *ssl, SOCKET s ) { this->s = s; clientAddr = client; this->ssl = ssl; downStreamBytes = 0; upStreamBytes = 0; ref = 1; } // Destruktor SSLSKlient::~SSLSKlient() { trenne(); #ifdef WIN32 OPENSSL_thread_stop(); #endif } // nicht constant 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 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 ); } // Reference Counting SSLSKlient *SSLSKlient::getThis() { ref++; return this; } SSLSKlient *SSLSKlient::release() { if( !--ref ) delete this; return 0; }