Beginning of TLS workings.
This commit is contained in:
		
							parent
							
								
									b2bdb522b3
								
							
						
					
					
						commit
						519faa535b
					
				
							
								
								
									
										174
									
								
								TLS.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								TLS.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | ||||
| #include "TLS.h" | ||||
| #include "EPoll.h" | ||||
| #include "TCPSession.h" | ||||
| #include "Exception.h" | ||||
| 
 | ||||
| namespace core { | ||||
|     | ||||
|    static pthread_mutex_t *lockarray; | ||||
| 
 | ||||
|    static unsigned long thread_id(void) {	 | ||||
|       return ((unsigned long) pthread_self()); | ||||
|    } | ||||
|     | ||||
|    static void lock_callback(int mode, int type, const char *file, int line) { | ||||
|       if(mode & CRYPTO_LOCK)   | ||||
|         pthread_mutex_lock(&(lockarray[type]));    | ||||
|       else  | ||||
|         pthread_mutex_unlock(&(lockarray[type])); | ||||
|    } | ||||
|     | ||||
|    TLS::TLS() { | ||||
| 
 | ||||
|       SSL_library_init(); | ||||
|       SSL_load_error_strings(); | ||||
|        | ||||
|       lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); | ||||
|       for(int i = 0; i < CRYPTO_num_locks(); ++i)  | ||||
|       pthread_mutex_init(&(lockarray[i]), NULL); | ||||
|        | ||||
|       CRYPTO_set_id_callback((unsigned long (*)())thread_id); | ||||
|       CRYPTO_set_locking_callback((void (*)(int, int, const char *, int))lock_callback); | ||||
|        | ||||
|       SSLeay_add_ssl_algorithms(); | ||||
|       RAND_load_file("/dev/hwrng", 1024);    | ||||
| 
 | ||||
|       if(!(ctx = SSL_CTX_new(SSLv23_server_method())))  | ||||
|         throw coreutils::Exception("Error while setting server method SSLv23.");      | ||||
|       SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | ||||
|       SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); | ||||
|       SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); | ||||
|       //   SSL_CTX_set_generate_session_id(ctx, generate_session_id);
 | ||||
|       SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA"); | ||||
|       if(SSL_CTX_use_certificate_file(ctx, sip_cert, SSL_FILETYPE_PEM) <= 0)  | ||||
|         throw coreutils::Exception("Error looking up certificate."); | ||||
|       if(SSL_CTX_use_PrivateKey_file(ctx, sip_key, SSL_FILETYPE_PEM) < 0) | ||||
|         throw coreutils::Exception("Error with private key."); | ||||
|       if(SSL_CTX_check_private_key(ctx) != 1) | ||||
|         throw coreutils::Exception("Private key does not match certificate."); | ||||
|       SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); | ||||
|       SSL_CTX_set_verify_depth(ctx, 1); | ||||
|       if(!SSL_CTX_load_verify_locations(ctx, sip_cacert, NULL)) | ||||
|         throw coreutils::Exception("Cannot verify locations."); | ||||
|       SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(sip_cacert));        | ||||
|       coreutils::Log(coreutils::LOG_DEBUG_1) << "Server key authenticated."; | ||||
|    } | ||||
|     | ||||
|    TLS::~TLS() {} | ||||
|     | ||||
|    static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) { | ||||
|       char *session_id_prefix = (char *)"BARANT"; | ||||
|       unsigned int count = 0; | ||||
|       coreutils::Log(coreutils::LOG_DEBUG_3) << "Generating unique session id."; | ||||
|       do { | ||||
| 	 RAND_bytes(id, *id_len); | ||||
| 	 memcpy(id, session_id_prefix, (strlen(session_id_prefix) < *id_len)); | ||||
|       } while(SSL_has_matching_session_id(ssl, id, *id_len) && (++count < 10)); | ||||
|       return 1; | ||||
|    } | ||||
|     | ||||
|    void handshake_complete(const SSL *ssl, int where, int ret) { | ||||
|       coreutils::Log(coreutils::LOG_DEBUG_3) << "==>" << SSL_state_string_long(ssl) << "<==" << ret; | ||||
|       if(where & SSL_CB_HANDSHAKE_DONE) { | ||||
| 	 X509 *ssl_client_cert = SSL_get_peer_certificate(ssl); | ||||
| 	 if(!ssl_client_cert)  | ||||
| 	   throw std::string("Unable to get peer certificate."); | ||||
| 	 X509_free(ssl_client_cert); | ||||
| 	 if(SSL_get_verify_result(ssl) != X509_V_OK) | ||||
| 	   throw std::string("Certificate verification failed."); | ||||
| 	 coreutils::Log(coreutils::LOG_DEBUG_3) << "Certificate verified successfully."; | ||||
|       } | ||||
|       else  | ||||
| 	coreutils::Log(coreutils::LOG_DEBUG_3) << "No client certificate."; | ||||
|    } | ||||
|     | ||||
|    TLSSession::TLSSession(EPoll &ePoll, TCPServer &server) : TCPSession(ePoll, server) {} | ||||
| 
 | ||||
|    void TLSSession::onRegister() {	 | ||||
|       initialized = true; | ||||
|       int ret; | ||||
| 
 | ||||
|       coreutils::Log(coreutils::LOG_DEBUG_3) << "TLS socket initializing on socket " << getDescriptor() << "...";       | ||||
| 
 | ||||
|       fcntl(getDescriptor(), F_SETFL, fcntl(getDescriptor(), F_GETFL, 0) | O_NONBLOCK); | ||||
|        | ||||
|       ssl = SSL_new(static_cast<TLSServer &>(server).ctx); | ||||
| //      if(ssl <= 0)
 | ||||
| //	throw std::string("Error creating new TLS socket.");     
 | ||||
|        | ||||
|       SSL_set_info_callback(ssl, handshake_complete); | ||||
|        | ||||
|       if((ret = SSL_set_fd(ssl, getDescriptor())) == 0) | ||||
| 	throw std::string("Error setting TLS socket descriptor.");      | ||||
|        | ||||
| //      if(!SSL_set_generate_session_id(ssl, generate_session_id))
 | ||||
| //	throw std::string("Error setting session identifier callback.");
 | ||||
| 
 | ||||
|    } | ||||
|     | ||||
|    void TLSSession::onRegistered() {	 | ||||
| 
 | ||||
|       switch (SSL_get_error(ssl, SSL_accept(ssl))) { | ||||
|        case SSL_ERROR_SSL: | ||||
|          coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SSL on ssl_accept. errno=" << errno; | ||||
|          break; | ||||
|        case SSL_ERROR_WANT_READ: | ||||
|          coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_READ on ssl_accept."; | ||||
|          break; | ||||
|        case SSL_ERROR_WANT_WRITE: | ||||
|          coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_WRITE on ssl_accept."; | ||||
|          break; | ||||
|        case SSL_ERROR_SYSCALL: | ||||
|          coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SYSCALL on ssl_accept. errno=" << errno; | ||||
|          shutdown(); | ||||
|          break; | ||||
|        default: | ||||
|          coreutils::Log(coreutils::LOG_DEBUG_3) << "Unknown ERROR on ssl_accept."; | ||||
|          break; | ||||
|       } | ||||
|        | ||||
|    } | ||||
|     | ||||
|    TLSSession::~TLSSession() {} | ||||
|     | ||||
|    void TLSSession::protocol(coreutils::ZString &data) {} | ||||
|     | ||||
|    void TLSSession::receiveData(coreutils::ZString &buffer) { | ||||
|        | ||||
|       int len; | ||||
|       //   int error = -1;
 | ||||
|       // 
 | ||||
|       std::cout << "receiveData TLS" << std::endl; | ||||
|        | ||||
|       if((len = ::SSL_read(ssl, buffer.getData(), buffer.getLength())) >= 0) { | ||||
| 	 std::cout << "receiveData TLS...len=" << len << ":" << buffer << std::endl; | ||||
| 	 onDataReceived(buffer);              | ||||
|       } | ||||
|       else { | ||||
| 	 switch (SSL_get_error(ssl, len)) { | ||||
| 	  case SSL_ERROR_SSL: | ||||
| 	    coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SSL on ssl_read. error=" << errno; | ||||
| 	    break; | ||||
| 	  case SSL_ERROR_WANT_READ: | ||||
| 	    coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_READ on ssl_read."; | ||||
| 	    break; | ||||
| 	  case SSL_ERROR_WANT_WRITE: | ||||
| 	    coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_WRITE on ssl_read."; | ||||
| 	    break; | ||||
| 	  case SSL_ERROR_SYSCALL: | ||||
| 	    coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SYSCALL on ssl_read. errno=" << errno; | ||||
| 	    break; | ||||
| 	  default: | ||||
| 	    coreutils::Log(coreutils::LOG_DEBUG_3) << "Unknown ERROR on ssl_read."; | ||||
| 	    break; | ||||
| 	 } | ||||
|       } | ||||
| 
 | ||||
|    } | ||||
|     | ||||
|    void TLSSession::output(std::stringstream &out) { | ||||
|       out << "|" << ipAddress.getClientAddressAndPort();    | ||||
|    } | ||||
|     | ||||
| } | ||||
|     | ||||
							
								
								
									
										65
									
								
								TLS.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								TLS.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| #ifndef TLSServerSocket_h__ | ||||
| #define TLSServerSocket_h__ | ||||
| 
 | ||||
| #include "Socket.h" | ||||
| #include "TCPServer.h" | ||||
| #include "Command.h" | ||||
| #include "TCPSession.h" | ||||
| #include "IPAddress.h" | ||||
| 
 | ||||
| namespace core { | ||||
|     | ||||
|    ///
 | ||||
|    /// TLS
 | ||||
|    ///
 | ||||
|    /// This object provides the support methods to handle TLS on the server core and
 | ||||
|    /// session environment.
 | ||||
|    ///
 | ||||
|     | ||||
|    class TLS { | ||||
|        | ||||
|     public: | ||||
| 
 | ||||
|       TLS(); | ||||
|        | ||||
|       ///
 | ||||
|       /// The destructor for this object.
 | ||||
|       ///
 | ||||
|        | ||||
|       ~TLS();  | ||||
| 
 | ||||
|       SSL_CTX *ctx;    | ||||
|              | ||||
|     private: | ||||
| 
 | ||||
|       char *sip_cacert = (char *)"../testkeys/certs/pbxca.crt"; | ||||
|       char *sip_cert = (char *)"../testkeys/certs/pbxserver.crt"; | ||||
|       char *sip_key = (char *)"../testkeys/certs/pbxserver.key"; | ||||
|       | ||||
| 
 | ||||
|     public: | ||||
|        | ||||
|       ///
 | ||||
|       /// The output method is called by a socket session (Session) and
 | ||||
|       /// will output the detail information for the client socket. When extending 
 | ||||
|       /// TLSSocket or Session you can override the method to add attributes 
 | ||||
|       /// to the list. 
 | ||||
|       ///
 | ||||
|        | ||||
|       virtual void output(std::stringstream &out); | ||||
|       virtual void protocol(coreutils::ZString &data) override; | ||||
|        | ||||
|     protected: | ||||
|       void receiveData(coreutils::ZString &buffer) override; | ||||
|       void onRegister(); | ||||
|       void onRegistered(); | ||||
|        | ||||
|     private: | ||||
|       bool initialized = false; | ||||
|       SSL *ssl; | ||||
|        | ||||
|    }; | ||||
|     | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Brad Arant
						Brad Arant