From 02841e3c67c92006f9fe08efcda0d15f3d7283c5 Mon Sep 17 00:00:00 2001 From: Raymaekers Luca Date: Thu, 2 Oct 2025 12:42:29 +0200 Subject: checkpoint --- ws/libs/wsServer/src/handshake.c | 144 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 ws/libs/wsServer/src/handshake.c (limited to 'ws/libs/wsServer/src/handshake.c') diff --git a/ws/libs/wsServer/src/handshake.c b/ws/libs/wsServer/src/handshake.c new file mode 100644 index 0000000..4b8ac30 --- /dev/null +++ b/ws/libs/wsServer/src/handshake.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2016-2024 Davidson Francis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +#include +#include +#include +#include + +/** + * @dir src/ + * @brief Handshake routines directory + * + * @file handshake.c + * @brief Handshake routines. + */ + +/** + * @brief Gets the field Sec-WebSocket-Accept on response, by + * an previously informed key. + * + * @param wsKey Sec-WebSocket-Key + * @param dest source to be stored the value. + * + * @return Returns 0 if success and a negative number + * otherwise. + * + * @attention This is part of the internal API and is documented just + * for completeness. + */ +int get_handshake_accept(char *wsKey, unsigned char **dest) +{ + unsigned char hash[SHA1HashSize]; /* SHA-1 Hash. */ + SHA1Context ctx; /* SHA-1 Context. */ + char *str; /* WebSocket key + magic string. */ + + /* Invalid key. */ + if (!wsKey) + return (-1); + + str = calloc(1, sizeof(char) * (WS_KEY_LEN + WS_MS_LEN + 1)); + if (!str) + return (-1); + + strncpy(str, wsKey, WS_KEY_LEN); + strcat(str, MAGIC_STRING); + + SHA1Reset(&ctx); + SHA1Input(&ctx, (const uint8_t *)str, WS_KEYMS_LEN); + SHA1Result(&ctx, hash); + + *dest = base64_encode(hash, SHA1HashSize, NULL); + *(*dest + strlen((const char *)*dest) - 1) = '\0'; + free(str); + return (0); +} + +/** + * @brief Finds the ocorrence of @p needle in @p haystack, case + * insensitive. + * + * @param haystack Target string to be searched. + * @param needle Substring to search for. + * + * @returns If found, returns a pointer at the beginning of the + * found substring. Otherwise, returns NULL. + */ +static char *strstricase(const char *haystack, const char *needle) +{ + size_t length; + for (length = strlen(needle); *haystack; haystack++) + if (!strncasecmp(haystack, needle, length)) + return (char*)haystack; + return (NULL); +} + +/** + * @brief Gets the complete response to accomplish a succesfully + * handshake. + * + * @param hsrequest Client request. + * @param hsresponse Server response. + * + * @return Returns 0 if success and a negative number + * otherwise. + * + * @attention This is part of the internal API and is documented just + * for completeness. + */ +int get_handshake_response(char *hsrequest, char **hsresponse) +{ + unsigned char *accept; /* Accept message. */ + char *saveptr; /* strtok_r() pointer. */ + char *s; /* Current string. */ + int ret; /* Return value. */ + + saveptr = NULL; + for (s = strtok_r(hsrequest, "\r\n", &saveptr); s != NULL; + s = strtok_r(NULL, "\r\n", &saveptr)) + { + if (strstricase(s, WS_HS_REQ) != NULL) + break; + } + + /* Ensure that we have a valid pointer. */ + if (s == NULL) + return (-1); + + saveptr = NULL; + s = strtok_r(s, " ", &saveptr); + s = strtok_r(NULL, " ", &saveptr); + + ret = get_handshake_accept(s, &accept); + if (ret < 0) + return (ret); + + *hsresponse = malloc(sizeof(char) * WS_HS_ACCLEN); + if (*hsresponse == NULL) + return (-1); + + strcpy(*hsresponse, WS_HS_ACCEPT); + strcat(*hsresponse, (const char *)accept); + strcat(*hsresponse, "\r\n\r\n"); + + free(accept); + return (0); +} -- cgit v1.2.3-70-g09d2