mirror of
https://github.com/Team-Resurgent/BearSSL-OG.git
synced 2026-04-30 10:36:59 -07:00
Server stop was broken. Fixed it. Threads clean up proper. Client was passing structs by value like an idiot. Pointers now. Missing headers. Added em. string.h stdlib.h. Simple stuff. Xbox random numbers were weak. Now we seed with real entropy. Time API was wrong for Xbox. KeQuerySystemTime from the kernel. stdint.h had redefinition problems. Guards everywhere. Header guards missing on cert files. Done. Include paths only in Debug config. Now all configs got em. Typo in main.cpp. Quote was missing. Fixed. God's blessing on this Xbox SSL implementation.
300 lines
6.3 KiB
C++
300 lines
6.3 KiB
C++
#include "server.h"
|
|
#include "debug_utility.h"
|
|
#include "socket_utility.h"
|
|
|
|
#include <xtl.h>
|
|
#include <winsockx.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <bearssl.h>
|
|
|
|
#if !(SERVER_RSA || SERVER_EC || SERVER_MIXED)
|
|
#define SERVER_RSA 1
|
|
#define SERVER_EC 0
|
|
#define SERVER_MIXED 0
|
|
#endif
|
|
|
|
#if SERVER_RSA
|
|
#include "chain-rsa.h"
|
|
#include "key-rsa.h"
|
|
#define SKEY RSA
|
|
#elif SERVER_EC
|
|
#include "chain-ec.h"
|
|
#include "key-ec.h"
|
|
#define SKEY EC
|
|
#elif SERVER_MIXED
|
|
#include "chain-ec+rsa.h"
|
|
#include "key-ec.h"
|
|
#define SKEY EC
|
|
#else
|
|
#error Must use one of RSA, EC or MIXED chains.
|
|
#endif
|
|
|
|
|
|
#define MAX_NUM_THREADS 5
|
|
|
|
typedef struct {
|
|
int client_socket;
|
|
int thread_complete;
|
|
uint16_t port;
|
|
} thread_info_t;
|
|
|
|
typedef struct {
|
|
int active;
|
|
thread_info_t data;
|
|
HANDLE thread;
|
|
} pthread_info_t;
|
|
|
|
static pthread_info_t threads[MAX_NUM_THREADS];
|
|
static volatile bool server_running = false;
|
|
static int listen_socket_global = INVALID_SOCKET;
|
|
|
|
static const char *HTTP_RES =
|
|
"HTTP/1.1 200 OK\r\n"
|
|
"Cache-Control: no-store, no-cache, must-revalidate\r\n"
|
|
"Pragma: no-cache\r\n"
|
|
"Expires: 0\r\n"
|
|
//"Content-Length: 46\r\n"
|
|
"Connection: close\r\n"
|
|
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
|
"\r\n"
|
|
"<head><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css\"></head>"
|
|
"<html>\r\n"
|
|
"<body>\r\n"
|
|
"<main class=\"container\"><h1>BearSSL Test by EqUiNoX</h1><a href=\"https://doomonline1.vercel.app/dos.html\" target=\"_blank\">Play Doom</a></main>\r\n"
|
|
"</body>\r\n"
|
|
"</html>\r\n";
|
|
|
|
|
|
static void client_process(void* data)
|
|
{
|
|
thread_info_t *thread_info = (thread_info_t*)data;
|
|
|
|
unsigned char io_buffer[BR_SSL_BUFSIZE_BIDI];
|
|
|
|
br_ssl_server_context server_context;
|
|
|
|
#if SERVER_RSA /* RSA */
|
|
#if SERVER_PROFILE_MIN_FS
|
|
#if SERVER_CHACHA20
|
|
br_ssl_server_init_mine2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_mine2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#endif
|
|
#elif SERVER_PROFILE_MIN_NOFS
|
|
br_ssl_server_init_minr2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_full_rsa(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#endif
|
|
#elif SERVER_EC /* EC */
|
|
#if SERVER_PROFILE_MIN_FS
|
|
#if SERVER_CHACHA20
|
|
br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#endif
|
|
#elif SERVER_PROFILE_MIN_NOFS
|
|
br_ssl_server_init_minv2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_EC, &SKEY);
|
|
#endif
|
|
#else /* SERVER_MIXED */
|
|
#if SERVER_PROFILE_MIN_FS
|
|
#if SERVER_CHACHA20
|
|
br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#endif
|
|
#elif SERVER_PROFILE_MIN_NOFS
|
|
br_ssl_server_init_minu2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
|
|
#else
|
|
br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_RSA, &SKEY);
|
|
#endif
|
|
#endif
|
|
|
|
br_ssl_engine_set_buffer(&server_context.eng, io_buffer, BR_SSL_BUFSIZE_BIDI, 1);
|
|
br_ssl_server_reset(&server_context);
|
|
|
|
br_sslio_context io_context;
|
|
br_sslio_init(&io_context, &server_context.eng, socket_utility::socket_read, &thread_info->client_socket, socket_utility::socket_write, &thread_info->client_socket);
|
|
|
|
bool client_dropped = false;
|
|
|
|
int feed_count = 0;
|
|
while (true)
|
|
{
|
|
unsigned char current_char;
|
|
if (br_sslio_read(&io_context, ¤t_char, 1) < 0)
|
|
{
|
|
client_dropped = true;
|
|
break;
|
|
}
|
|
if (current_char == 0x0D)
|
|
{
|
|
continue;
|
|
}
|
|
if (current_char == 0x0A)
|
|
{
|
|
if (feed_count == 1)
|
|
{
|
|
break;
|
|
}
|
|
feed_count = 1;
|
|
}
|
|
else
|
|
{
|
|
feed_count = 0;
|
|
}
|
|
}
|
|
|
|
if (client_dropped == false)
|
|
{
|
|
br_sslio_write_all(&io_context, HTTP_RES, strlen(HTTP_RES));
|
|
}
|
|
|
|
int error = br_ssl_engine_last_error(&server_context.eng);
|
|
if (error == 0)
|
|
{
|
|
debug_utility::debug_print("SSL closed (correctly).\n");
|
|
}
|
|
else
|
|
{
|
|
debug_utility::debug_print("SSL error: %d\n", error);
|
|
}
|
|
|
|
br_sslio_close(&io_context);
|
|
closesocket(thread_info->client_socket);
|
|
|
|
thread_info->thread_complete = 1;
|
|
}
|
|
|
|
static uint64_t WINAPI process(void* data)
|
|
{
|
|
uint16_t port = (uint16_t)data;
|
|
|
|
int listen_socket = socket_utility::host_bind(port);
|
|
if (listen_socket == INVALID_SOCKET)
|
|
{
|
|
server_running = false;
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
listen_socket_global = listen_socket;
|
|
|
|
while (server_running)
|
|
{
|
|
int read_status = socket_utility::get_read_status(listen_socket);
|
|
if (read_status == SOCKET_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int client_socket = INVALID_SOCKET;
|
|
if (read_status == 1)
|
|
{
|
|
client_socket = socket_utility::accept_client(listen_socket);
|
|
}
|
|
else
|
|
{
|
|
Sleep(50);
|
|
continue;
|
|
}
|
|
|
|
if (client_socket == INVALID_SOCKET)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int i;
|
|
for (i = 0; i < MAX_NUM_THREADS; i++)
|
|
{
|
|
if (threads[i].active == 0)
|
|
{
|
|
break;
|
|
}
|
|
if (threads[i].data.thread_complete == 1)
|
|
{
|
|
CloseHandle(threads[i].thread);
|
|
memset(&threads[i], 0, sizeof(pthread_info_t));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == MAX_NUM_THREADS)
|
|
{
|
|
closesocket(client_socket);
|
|
continue;
|
|
}
|
|
|
|
threads[i].active = 1;
|
|
threads[i].data.client_socket = client_socket;
|
|
threads[i].data.port = port;
|
|
threads[i].thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)client_process, (void*)&threads[i].data, 0, NULL);
|
|
}
|
|
|
|
closesocket(listen_socket);
|
|
listen_socket_global = INVALID_SOCKET;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
server::server()
|
|
: thread(NULL), running(false)
|
|
{
|
|
}
|
|
|
|
void server::start(uint16_t port)
|
|
{
|
|
memset(threads, 0, sizeof(threads));
|
|
running = true;
|
|
server_running = true;
|
|
thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)port, 0, NULL);
|
|
}
|
|
|
|
void server::stop()
|
|
{
|
|
if (!running)
|
|
{
|
|
return;
|
|
}
|
|
|
|
running = false;
|
|
server_running = false;
|
|
|
|
// Close the listening socket to unblock accept
|
|
if (listen_socket_global != INVALID_SOCKET)
|
|
{
|
|
closesocket(listen_socket_global);
|
|
}
|
|
|
|
// Wait for the main server thread to finish
|
|
if (thread != NULL)
|
|
{
|
|
WaitForSingleObject(thread, 5000);
|
|
CloseHandle(thread);
|
|
thread = NULL;
|
|
}
|
|
|
|
// Wait for all client threads to complete
|
|
for (int i = 0; i < MAX_NUM_THREADS; i++)
|
|
{
|
|
if (threads[i].active && threads[i].thread != NULL)
|
|
{
|
|
WaitForSingleObject(threads[i].thread, 2000);
|
|
CloseHandle(threads[i].thread);
|
|
}
|
|
}
|
|
|
|
memset(threads, 0, sizeof(threads));
|
|
}
|
|
|
|
bool server::is_running()
|
|
{
|
|
return running;
|
|
}
|
|
|
|
|
|
|
|
|