diff options
Diffstat (limited to 'https_server.h')
-rw-r--r-- | https_server.h | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/https_server.h b/https_server.h new file mode 100644 index 0000000..4b1776f --- /dev/null +++ b/https_server.h @@ -0,0 +1,152 @@ +#include "https_response.h" + +char *get_client_ip( server_socket_t *svd, client_info_t *cl_info ){ + cl_info->client_ip = (char*)malloc( 8192 * sizeof(char) ); + if ( inet_ntop(AF_INET, &svd->client_info.sin_addr, cl_info->client_ip, (socklen_t)(8192 * sizeof(char))) != NULL ) + return cl_info->client_ip; + return "Unknown"; +} + +void clear_client_ip( client_info_t *clf ){ + if ( clf->client_ip != NULL ){ + free( clf->client_ip ); + clf->client_ip = NULL; + } + return; +} + +void https_server_event_loop( server_socket_t *sv, client_info_t *cl, server_config_t *svcfg, webhooks_data_t *wdata, http_request_data_t *http_req_data, log_file_t *logf ){ + int ev_count = 0; + socklen_t cl_info_len = (socklen_t)sizeof( sv->client_info ); + while ( (ev_count = poll(sv->pstruct, 1, 0)) != -1 ){ + if ( ev_count > 0 ){ + sv->client_socket_fd = accept( sv->socket_fd, (struct sockaddr*)&sv->client_info, &cl_info_len ); + if ( sv->client_socket_fd == -1 ){ + log_write( svcfg, logf, "Error: failed to accept connection" ); + continue; + } + sv->tls_session = SSL_new( sv->tls_context ); + if ( sv->tls_session == NULL ){ + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + log_write( svcfg, logf, "Error: failed to create TLS session" ); + continue; + } + if ( SSL_set_fd(sv->tls_session, sv->client_socket_fd) != 1 ){ + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + log_write( svcfg, logf, "Error: failed to set client file descriptor" ); + continue; + } + SSL_set_accept_state( sv->tls_session ); + if ( SSL_accept(sv->tls_session) != 1 ){ + if ( sv->tls_session != NULL ) + SSL_shutdown( sv->tls_session ); + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + log_write( svcfg, logf, "Error: failed to initiate handshake" ); + continue; + } + if ( strcmp((const char*)svcfg->log_enabled->valuestring, "yes") == 0 ){ + fprintf( logf->log_file, "Received connection from %s\n", get_client_ip(sv, cl) ); + clear_client_ip( cl ); + } + sv->recv_peek = (char*)calloc( (size_t)((uint64_t)MAX_PEEK_BYTES), sizeof(char) ); + if ( sv->recv_peek == NULL ){ + SSL_shutdown( sv->tls_session ); + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + log_write( svcfg, logf, "Error: failed to allocate memory for reading amount of incoming data" ); + continue; + } + sv->recv_pending_bytes = (long long int)SSL_peek( sv->tls_session, sv->recv_peek, (long long int)MAX_PEEK_BYTES ); + if ( sv->recv_pending_bytes <= 0 || SSL_get_error(sv->tls_session, sv->recv_pending_bytes) != SSL_ERROR_NONE ){ + free( sv->recv_peek ); + sv->recv_peek = NULL; + SSL_shutdown( sv->tls_session ); + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + sv->recv_pending_bytes = 0; + log_write( svcfg, logf, "Error: no bytes were received" ); + continue; + } + free( sv->recv_peek ); + sv->recv_peek = NULL; + if ( sv->recv_pending_bytes > (long long int)MAX_RECV_BYTES ){ + SSL_shutdown( sv->tls_session ); + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + log_write( svcfg, logf, "Error: too many bytes received" ); + continue; + } + sv->recv_data = (char*)calloc( (size_t)sv->recv_pending_bytes, sizeof(char) ); + if ( sv->recv_data == NULL ){ + SSL_shutdown( sv->tls_session ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + log_write( svcfg, logf, "Error: failed to allocate memory for received bytes" ); + continue; + } + sv->recv_read_bytes = (long long int)SSL_read( sv->tls_session, sv->recv_data, sv->recv_pending_bytes ); + if ( sv->recv_read_bytes > 0 && SSL_get_error(sv->tls_session, sv->recv_read_bytes) == SSL_ERROR_NONE ){ + int res_status = send_response( sv, svcfg, wdata, http_req_data, logf ); + if ( res_status == RES_SUCCESS ){ + log_write( svcfg, logf, "Success, response sent" ); + } + else if ( res_status == RES_UNAUTHORIZED ){ + log_write( svcfg, logf, "Error: unauthorized request" ); + } + else + { + log_write( svcfg, logf, "Error: failed to send response" ); + } + res_status = 0; + } + else + { + log_write( svcfg, logf, "Error: no bytes received" ); + } + sv->recv_pending_bytes = 0; + sv->recv_read_bytes = 0; + free( sv->recv_data ); + sv->recv_data = NULL; + SSL_shutdown( sv->tls_session ); + shutdown( sv->client_socket_fd, SHUT_RDWR ); + close( sv->client_socket_fd ); + if ( sv->tls_session != NULL ) + SSL_free( sv->tls_session ); + } + } + perror( "poll" ); + cl_info_len = 0; + ev_count = 0; + return; +} + +void server_start( server_socket_t *srv, client_info_t *cli, server_config_t *sconf, webhooks_data_t *whdata, http_request_data_t *hreq, log_file_t *lfdt ){ + fputs( "Starting server\n", stdout ); + memset( &srv->client_info, 0, sizeof(srv->client_info) ); + whdata->wh_command = NULL; + whdata->wh_response = NULL; + whdata->wh_output = NULL; + srv->pstruct[0].fd = srv->socket_fd; + srv->pstruct[0].events = POLLIN; + if ( listen(srv->socket_fd, 1024) == -1 ){ + fputs( "Failed to start listening for connections\n", stderr ); + return; + } + fputs( "Server started\n", stdout ); + https_server_event_loop( srv, cli, sconf, whdata, hreq, lfdt ); + return; +} |