#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 ){ int64_t ev_count = 0; socklen_t cl_info_len = (socklen_t)sizeof( sv->client_info ); while ( (ev_count = (int64_t)poll(sv->pstruct, 1, 0)) != -1 ){ if ( (ev_count > 0) && sv->pstruct->revents & POLLIN ){ 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 = (int64_t)SSL_peek( sv->tls_session, sv->recv_peek, (int64_t)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 > (int64_t)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 = (int64_t)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; }