2014-09-04 14:55:28 +02:00
|
|
|
/*
|
2021-12-21 06:14:10 +01:00
|
|
|
* UDP proxy: emulate an unreliable UDP connection for DTLS testing
|
2014-09-04 14:55:28 +02:00
|
|
|
*
|
2020-08-07 13:07:28 +02:00
|
|
|
* Copyright The Mbed TLS Contributors
|
2015-09-04 14:21:07 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2014-09-04 14:55:28 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2014-09-04 14:55:28 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2014-09-04 14:55:28 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2014-09-04 14:55:28 +02:00
|
|
|
*/
|
|
|
|
|
2015-06-30 15:40:39 +02:00
|
|
|
/*
|
|
|
|
* Warning: this is an internal utility program we use for tests.
|
|
|
|
* It does break some abstractions from the NET layer, and is thus NOT an
|
|
|
|
* example of good general usage.
|
|
|
|
*/
|
|
|
|
|
2021-05-19 17:54:54 +02:00
|
|
|
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
|
|
|
|
2021-05-27 11:25:03 +02:00
|
|
|
#include "mbedtls/build_info.h"
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if defined(MBEDTLS_PLATFORM_C)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/platform.h"
|
2015-01-29 14:29:20 +01:00
|
|
|
#else
|
2016-04-27 02:26:50 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2021-11-29 18:28:13 +01:00
|
|
|
#if defined(MBEDTLS_HAVE_TIME)
|
2016-04-27 02:26:50 +02:00
|
|
|
#include <time.h>
|
2018-04-29 22:58:53 +02:00
|
|
|
#define mbedtls_time time
|
|
|
|
#define mbedtls_time_t time_t
|
2021-11-29 18:28:13 +01:00
|
|
|
#endif
|
2018-04-29 22:58:53 +02:00
|
|
|
#define mbedtls_printf printf
|
2018-08-17 14:33:41 +02:00
|
|
|
#define mbedtls_calloc calloc
|
|
|
|
#define mbedtls_free free
|
2019-05-23 09:46:47 +02:00
|
|
|
#define mbedtls_exit exit
|
2018-04-30 23:42:33 +02:00
|
|
|
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
|
2018-04-29 22:58:53 +02:00
|
|
|
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
|
|
|
|
#endif /* MBEDTLS_PLATFORM_C */
|
2015-01-29 14:29:20 +01:00
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if !defined(MBEDTLS_NET_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
int main(void)
|
2014-09-04 14:55:28 +02:00
|
|
|
{
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf("MBEDTLS_NET_C not defined.\n");
|
|
|
|
mbedtls_exit(0);
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
2016-09-14 15:32:09 +02:00
|
|
|
#include "mbedtls/net_sockets.h"
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/error.h"
|
|
|
|
#include "mbedtls/ssl.h"
|
2017-10-31 15:10:07 +01:00
|
|
|
#include "mbedtls/timing.h"
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2015-02-16 19:37:53 +01:00
|
|
|
#include <string.h>
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
/* For select() */
|
|
|
|
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
|
|
|
|
!defined(EFI32)
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#if defined(_WIN32_WCE)
|
|
|
|
#pragma comment( lib, "ws2.lib" )
|
|
|
|
#else
|
|
|
|
#pragma comment( lib, "ws2_32.lib" )
|
|
|
|
#endif
|
|
|
|
#endif /* _MSC_VER */
|
|
|
|
#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
2022-05-11 18:05:16 +02:00
|
|
|
#if defined(MBEDTLS_HAVE_TIME) || (defined(MBEDTLS_TIMING_C) && !defined(MBEDTLS_TIMING_ALT))
|
2014-09-04 14:55:28 +02:00
|
|
|
#include <sys/time.h>
|
2022-03-02 18:01:10 +01:00
|
|
|
#endif
|
2022-05-11 18:05:16 +02:00
|
|
|
#include <sys/select.h>
|
2014-09-04 14:55:28 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
|
|
|
|
2014-09-23 12:17:30 +02:00
|
|
|
#define MAX_MSG_SIZE 16384 + 2048 /* max record/datagram size */
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
#define DFL_SERVER_ADDR "localhost"
|
2015-06-23 12:30:57 +02:00
|
|
|
#define DFL_SERVER_PORT "4433"
|
2014-09-04 14:55:28 +02:00
|
|
|
#define DFL_LISTEN_ADDR "localhost"
|
2015-06-23 12:30:57 +02:00
|
|
|
#define DFL_LISTEN_PORT "5556"
|
2017-05-22 15:30:59 +02:00
|
|
|
#define DFL_PACK 0
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2017-10-31 15:10:07 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
|
|
|
#define USAGE_PACK \
|
|
|
|
" pack=%%d default: 0 (don't pack)\n" \
|
|
|
|
" options: t > 0 (pack for t milliseconds)\n"
|
|
|
|
#else
|
|
|
|
#define USAGE_PACK
|
|
|
|
#endif
|
|
|
|
|
2014-09-06 08:07:45 +02:00
|
|
|
#define USAGE \
|
|
|
|
"\n usage: udp_proxy param=<>...\n" \
|
|
|
|
"\n acceptable parameters:\n" \
|
2014-09-25 17:00:27 +02:00
|
|
|
" server_addr=%%s default: localhost\n" \
|
2014-09-06 08:07:45 +02:00
|
|
|
" server_port=%%d default: 4433\n" \
|
2014-09-25 17:00:27 +02:00
|
|
|
" listen_addr=%%s default: localhost\n" \
|
2014-09-06 08:07:45 +02:00
|
|
|
" listen_port=%%d default: 4433\n" \
|
2014-09-06 08:14:47 +02:00
|
|
|
"\n" \
|
|
|
|
" duplicate=%%d default: 0 (no duplication)\n" \
|
2014-09-20 18:06:23 +02:00
|
|
|
" duplicate about 1:N packets randomly\n" \
|
2014-09-06 14:36:46 +02:00
|
|
|
" delay=%%d default: 0 (no delayed packets)\n" \
|
2014-09-20 18:06:23 +02:00
|
|
|
" delay about 1:N packets randomly\n" \
|
2014-09-25 17:00:27 +02:00
|
|
|
" delay_ccs=0/1 default: 0 (don't delay ChangeCipherSpec)\n" \
|
2023-01-11 14:50:10 +01:00
|
|
|
" delay_cli=%%s Handshake message from client that should be\n" \
|
2018-08-17 14:33:41 +02:00
|
|
|
" delayed. Possible values are 'ClientHello',\n" \
|
|
|
|
" 'Certificate', 'CertificateVerify', and\n" \
|
|
|
|
" 'ClientKeyExchange'.\n" \
|
2023-01-11 14:50:10 +01:00
|
|
|
" May be used multiple times, even for the same\n" \
|
|
|
|
" message, in which case the respective message\n" \
|
2018-08-17 14:33:41 +02:00
|
|
|
" gets delayed multiple times.\n" \
|
2023-01-11 14:50:10 +01:00
|
|
|
" delay_srv=%%s Handshake message from server that should be\n" \
|
|
|
|
" delayed. Possible values are 'HelloRequest',\n" \
|
|
|
|
" 'ServerHello', 'ServerHelloDone', 'Certificate'\n" \
|
|
|
|
" 'ServerKeyExchange', 'NewSessionTicket',\n" \
|
|
|
|
" 'HelloVerifyRequest' and ''CertificateRequest'.\n" \
|
|
|
|
" May be used multiple times, even for the same\n" \
|
|
|
|
" message, in which case the respective message\n" \
|
2018-08-17 14:33:41 +02:00
|
|
|
" gets delayed multiple times.\n" \
|
2014-09-06 14:49:52 +02:00
|
|
|
" drop=%%d default: 0 (no dropped packets)\n" \
|
2014-09-20 18:06:23 +02:00
|
|
|
" drop about 1:N packets randomly\n" \
|
2014-09-08 11:11:42 +02:00
|
|
|
" mtu=%%d default: 0 (unlimited)\n" \
|
|
|
|
" drop packets larger than N bytes\n" \
|
2014-09-25 17:00:27 +02:00
|
|
|
" bad_ad=0/1 default: 0 (don't add bad ApplicationData)\n" \
|
2019-05-24 11:07:42 +02:00
|
|
|
" bad_cid=%%d default: 0 (don't corrupt Connection IDs)\n" \
|
|
|
|
" duplicate 1:N packets containing a CID,\n" \
|
|
|
|
" modifying CID in first instance of the packet.\n" \
|
2014-09-25 17:00:27 +02:00
|
|
|
" protect_hvr=0/1 default: 0 (don't protect HelloVerifyRequest)\n" \
|
2017-10-31 15:10:07 +01:00
|
|
|
" protect_len=%%d default: (don't protect packets of this size)\n" \
|
2020-03-13 11:11:02 +01:00
|
|
|
" inject_clihlo=0/1 default: 0 (don't inject fake ClientHello)\n" \
|
2014-09-20 18:06:23 +02:00
|
|
|
"\n" \
|
|
|
|
" seed=%%d default: (use current time)\n" \
|
2017-10-31 15:10:07 +01:00
|
|
|
USAGE_PACK \
|
2014-09-06 08:07:45 +02:00
|
|
|
"\n"
|
|
|
|
|
2014-09-04 14:55:28 +02:00
|
|
|
/*
|
|
|
|
* global options
|
|
|
|
*/
|
2018-08-17 14:33:41 +02:00
|
|
|
|
|
|
|
#define MAX_DELAYED_HS 10
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static struct options {
|
2014-09-04 14:55:28 +02:00
|
|
|
const char *server_addr; /* address to forward packets to */
|
2015-06-23 12:30:57 +02:00
|
|
|
const char *server_port; /* port to forward packets to */
|
2014-09-04 14:55:28 +02:00
|
|
|
const char *listen_addr; /* address for accepting client connections */
|
2015-06-23 12:30:57 +02:00
|
|
|
const char *listen_port; /* port for accepting client connections */
|
2014-09-06 08:14:47 +02:00
|
|
|
|
|
|
|
int duplicate; /* duplicate 1 in N packets (none if 0) */
|
2014-09-06 14:36:46 +02:00
|
|
|
int delay; /* delay 1 packet in N (none if 0) */
|
2014-09-08 10:44:57 +02:00
|
|
|
int delay_ccs; /* delay ChangeCipherSpec */
|
2023-01-11 14:50:10 +01:00
|
|
|
char *delay_cli[MAX_DELAYED_HS]; /* handshake types of messages from
|
2018-08-28 12:15:32 +02:00
|
|
|
* client that should be delayed. */
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t delay_cli_cnt; /* Number of entries in delay_cli. */
|
2023-01-11 14:50:10 +01:00
|
|
|
char *delay_srv[MAX_DELAYED_HS]; /* handshake types of messages from
|
2018-08-28 12:15:32 +02:00
|
|
|
* server that should be delayed. */
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t delay_srv_cnt; /* Number of entries in delay_srv. */
|
2014-09-06 14:49:52 +02:00
|
|
|
int drop; /* drop 1 packet in N (none if 0) */
|
2014-09-08 11:11:42 +02:00
|
|
|
int mtu; /* drop packets larger than this */
|
2014-09-08 11:24:58 +02:00
|
|
|
int bad_ad; /* inject corrupted ApplicationData record */
|
2019-05-24 11:07:42 +02:00
|
|
|
unsigned bad_cid; /* inject corrupted CID record */
|
2014-09-25 17:00:27 +02:00
|
|
|
int protect_hvr; /* never drop or delay HelloVerifyRequest */
|
2014-10-09 16:13:44 +02:00
|
|
|
int protect_len; /* never drop/delay packet of the given size*/
|
2020-03-13 11:11:02 +01:00
|
|
|
int inject_clihlo; /* inject fake ClientHello after handshake */
|
2017-11-02 11:50:28 +01:00
|
|
|
unsigned pack; /* merge packets into single datagram for
|
2017-05-22 15:30:59 +02:00
|
|
|
* at most \c merge milliseconds if > 0 */
|
2014-09-20 18:06:23 +02:00
|
|
|
unsigned int seed; /* seed for "random" events */
|
|
|
|
} opt;
|
2014-09-06 08:14:47 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static void exit_usage(const char *name, const char *value)
|
2014-09-04 14:55:28 +02:00
|
|
|
{
|
2023-01-11 14:50:10 +01:00
|
|
|
if (value == NULL) {
|
|
|
|
mbedtls_printf(" unknown option or missing value: %s\n", name);
|
|
|
|
} else {
|
|
|
|
mbedtls_printf(" option %s: illegal value: %s\n", name, value);
|
|
|
|
}
|
2014-09-06 08:07:45 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(USAGE);
|
|
|
|
mbedtls_exit(1);
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static void get_options(int argc, char *argv[])
|
2014-09-04 14:55:28 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *p, *q;
|
|
|
|
|
|
|
|
opt.server_addr = DFL_SERVER_ADDR;
|
|
|
|
opt.server_port = DFL_SERVER_PORT;
|
|
|
|
opt.listen_addr = DFL_LISTEN_ADDR;
|
|
|
|
opt.listen_port = DFL_LISTEN_PORT;
|
2017-10-31 15:08:10 +01:00
|
|
|
opt.pack = DFL_PACK;
|
2014-09-06 14:49:52 +02:00
|
|
|
/* Other members default to 0 */
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2018-08-17 14:33:41 +02:00
|
|
|
opt.delay_cli_cnt = 0;
|
|
|
|
opt.delay_srv_cnt = 0;
|
2023-01-11 14:50:10 +01:00
|
|
|
memset(opt.delay_cli, 0, sizeof(opt.delay_cli));
|
|
|
|
memset(opt.delay_srv, 0, sizeof(opt.delay_srv));
|
2018-08-17 14:33:41 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
for (i = 1; i < argc; i++) {
|
2014-09-04 14:55:28 +02:00
|
|
|
p = argv[i];
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((q = strchr(p, '=')) == NULL) {
|
|
|
|
exit_usage(p, NULL);
|
|
|
|
}
|
2014-09-04 14:55:28 +02:00
|
|
|
*q++ = '\0';
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (strcmp(p, "server_addr") == 0) {
|
2014-09-04 14:55:28 +02:00
|
|
|
opt.server_addr = q;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (strcmp(p, "server_port") == 0) {
|
2015-06-23 12:30:57 +02:00
|
|
|
opt.server_port = q;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (strcmp(p, "listen_addr") == 0) {
|
2014-09-04 14:55:28 +02:00
|
|
|
opt.listen_addr = q;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (strcmp(p, "listen_port") == 0) {
|
2015-06-23 12:30:57 +02:00
|
|
|
opt.listen_port = q;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (strcmp(p, "duplicate") == 0) {
|
|
|
|
opt.duplicate = atoi(q);
|
|
|
|
if (opt.duplicate < 0 || opt.duplicate > 20) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "delay") == 0) {
|
|
|
|
opt.delay = atoi(q);
|
|
|
|
if (opt.delay < 0 || opt.delay > 20 || opt.delay == 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "delay_ccs") == 0) {
|
|
|
|
opt.delay_ccs = atoi(q);
|
|
|
|
if (opt.delay_ccs < 0 || opt.delay_ccs > 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "delay_cli") == 0 ||
|
|
|
|
strcmp(p, "delay_srv") == 0) {
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t *delay_cnt;
|
|
|
|
char **delay_list;
|
|
|
|
size_t len;
|
|
|
|
char *buf;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (strcmp(p, "delay_cli") == 0) {
|
2018-08-17 14:33:41 +02:00
|
|
|
delay_cnt = &opt.delay_cli_cnt;
|
|
|
|
delay_list = opt.delay_cli;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else {
|
2018-08-17 14:33:41 +02:00
|
|
|
delay_cnt = &opt.delay_srv_cnt;
|
|
|
|
delay_list = opt.delay_srv;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (*delay_cnt == MAX_DELAYED_HS) {
|
|
|
|
mbedtls_printf(" too many uses of %s: only %d allowed\n",
|
|
|
|
p, MAX_DELAYED_HS);
|
|
|
|
exit_usage(p, NULL);
|
2018-08-17 14:33:41 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
len = strlen(q);
|
|
|
|
buf = mbedtls_calloc(1, len + 1);
|
|
|
|
if (buf == NULL) {
|
|
|
|
mbedtls_printf(" Allocation failure\n");
|
|
|
|
exit(1);
|
2018-08-17 14:33:41 +02:00
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(buf, q, len + 1);
|
2018-08-17 14:33:41 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
delay_list[(*delay_cnt)++] = buf;
|
|
|
|
} else if (strcmp(p, "drop") == 0) {
|
|
|
|
opt.drop = atoi(q);
|
|
|
|
if (opt.drop < 0 || opt.drop > 20 || opt.drop == 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "pack") == 0) {
|
2017-10-31 15:10:07 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
opt.pack = (unsigned) atoi(q);
|
2017-10-31 15:10:07 +01:00
|
|
|
#else
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" option pack only defined if MBEDTLS_TIMING_C is enabled\n");
|
|
|
|
exit(1);
|
2017-10-31 15:10:07 +01:00
|
|
|
#endif
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (strcmp(p, "mtu") == 0) {
|
|
|
|
opt.mtu = atoi(q);
|
|
|
|
if (opt.mtu < 0 || opt.mtu > MAX_MSG_SIZE) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "bad_ad") == 0) {
|
|
|
|
opt.bad_ad = atoi(q);
|
|
|
|
if (opt.bad_ad < 0 || opt.bad_ad > 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
2014-09-08 11:24:58 +02:00
|
|
|
}
|
2019-05-24 11:07:42 +02:00
|
|
|
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
2023-01-11 14:50:10 +01:00
|
|
|
else if (strcmp(p, "bad_cid") == 0) {
|
|
|
|
opt.bad_cid = (unsigned) atoi(q);
|
2019-05-24 11:07:42 +02:00
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
2023-01-11 14:50:10 +01:00
|
|
|
else if (strcmp(p, "protect_hvr") == 0) {
|
|
|
|
opt.protect_hvr = atoi(q);
|
|
|
|
if (opt.protect_hvr < 0 || opt.protect_hvr > 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "protect_len") == 0) {
|
|
|
|
opt.protect_len = atoi(q);
|
|
|
|
if (opt.protect_len < 0) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "inject_clihlo") == 0) {
|
|
|
|
opt.inject_clihlo = atoi(q);
|
|
|
|
if (opt.inject_clihlo < 0 || opt.inject_clihlo > 1) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else if (strcmp(p, "seed") == 0) {
|
|
|
|
opt.seed = atoi(q);
|
|
|
|
if (opt.seed == 0) {
|
|
|
|
exit_usage(p, q);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
exit_usage(p, NULL);
|
2014-09-20 18:06:23 +02:00
|
|
|
}
|
2014-09-06 08:07:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static const char *msg_type(unsigned char *msg, size_t len)
|
2014-09-06 08:07:45 +02:00
|
|
|
{
|
2023-01-11 14:50:10 +01:00
|
|
|
if (len < 1) {
|
|
|
|
return "Invalid";
|
|
|
|
}
|
|
|
|
switch (msg[0]) {
|
|
|
|
case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: return "ChangeCipherSpec";
|
|
|
|
case MBEDTLS_SSL_MSG_ALERT: return "Alert";
|
|
|
|
case MBEDTLS_SSL_MSG_APPLICATION_DATA: return "ApplicationData";
|
|
|
|
case MBEDTLS_SSL_MSG_CID: return "CID";
|
2015-04-08 12:49:31 +02:00
|
|
|
case MBEDTLS_SSL_MSG_HANDSHAKE: break; /* See below */
|
2023-01-11 14:50:10 +01:00
|
|
|
default: return "Unknown";
|
2014-09-06 08:07:45 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (len < 13 + 12) {
|
|
|
|
return "Invalid handshake";
|
|
|
|
}
|
2014-09-25 12:59:05 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Our handshake message are less than 2^16 bytes long, so they should
|
|
|
|
* have 0 as the first byte of length, frag_offset and frag_length.
|
|
|
|
* Otherwise, assume they are encrypted.
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
if (msg[14] || msg[19] || msg[22]) {
|
|
|
|
return "Encrypted handshake";
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg[13]) {
|
|
|
|
case MBEDTLS_SSL_HS_HELLO_REQUEST: return "HelloRequest";
|
|
|
|
case MBEDTLS_SSL_HS_CLIENT_HELLO: return "ClientHello";
|
|
|
|
case MBEDTLS_SSL_HS_SERVER_HELLO: return "ServerHello";
|
|
|
|
case MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST: return "HelloVerifyRequest";
|
|
|
|
case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: return "NewSessionTicket";
|
|
|
|
case MBEDTLS_SSL_HS_CERTIFICATE: return "Certificate";
|
|
|
|
case MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE: return "ServerKeyExchange";
|
|
|
|
case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: return "CertificateRequest";
|
|
|
|
case MBEDTLS_SSL_HS_SERVER_HELLO_DONE: return "ServerHelloDone";
|
|
|
|
case MBEDTLS_SSL_HS_CERTIFICATE_VERIFY: return "CertificateVerify";
|
|
|
|
case MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE: return "ClientKeyExchange";
|
|
|
|
case MBEDTLS_SSL_HS_FINISHED: return "Finished";
|
|
|
|
default: return "Unknown handshake";
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-31 15:10:07 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2014-09-20 09:43:48 +02:00
|
|
|
/* Return elapsed time in milliseconds since the first call */
|
2023-01-11 14:50:10 +01:00
|
|
|
static unsigned elapsed_time(void)
|
2014-09-20 09:43:48 +02:00
|
|
|
{
|
2017-10-31 15:09:30 +01:00
|
|
|
static int initialized = 0;
|
|
|
|
static struct mbedtls_timing_hr_time hires;
|
2014-09-20 09:43:48 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (initialized == 0) {
|
|
|
|
(void) mbedtls_timing_get_timer(&hires, 1);
|
2017-10-31 15:09:30 +01:00
|
|
|
initialized = 1;
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2014-09-20 09:43:48 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return mbedtls_timing_get_timer(&hires, 0);
|
2014-09-20 09:43:48 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
typedef struct {
|
2017-05-22 15:30:59 +02:00
|
|
|
mbedtls_net_context *ctx;
|
|
|
|
|
|
|
|
const char *description;
|
|
|
|
|
2017-11-02 11:50:28 +01:00
|
|
|
unsigned packet_lifetime;
|
|
|
|
unsigned num_datagrams;
|
2017-05-22 15:30:59 +02:00
|
|
|
|
|
|
|
unsigned char data[MAX_MSG_SIZE];
|
2017-12-06 09:35:02 +01:00
|
|
|
size_t len;
|
2017-05-22 15:30:59 +02:00
|
|
|
|
|
|
|
} ctx_buffer;
|
|
|
|
|
|
|
|
static ctx_buffer outbuf[2];
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static int ctx_buffer_flush(ctx_buffer *buf)
|
2017-05-22 15:30:59 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" %05u flush %s: %u bytes, %u datagrams, last %u ms\n",
|
|
|
|
elapsed_time(), buf->description,
|
|
|
|
(unsigned) buf->len, buf->num_datagrams,
|
|
|
|
elapsed_time() - buf->packet_lifetime);
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
ret = mbedtls_net_send(buf->ctx, buf->data, buf->len);
|
2017-05-22 15:30:59 +02:00
|
|
|
|
|
|
|
buf->len = 0;
|
|
|
|
buf->num_datagrams = 0;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return ret;
|
2017-05-22 15:30:59 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static unsigned ctx_buffer_time_remaining(ctx_buffer *buf)
|
2017-05-22 15:30:59 +02:00
|
|
|
{
|
2022-12-04 18:19:59 +01:00
|
|
|
unsigned const cur_time = elapsed_time();
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (buf->num_datagrams == 0) {
|
|
|
|
return (unsigned) -1;
|
|
|
|
}
|
2017-11-02 11:50:28 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (cur_time - buf->packet_lifetime >= opt.pack) {
|
|
|
|
return 0;
|
|
|
|
}
|
2017-11-02 11:50:28 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return opt.pack - (cur_time - buf->packet_lifetime);
|
2017-05-22 15:30:59 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static int ctx_buffer_append(ctx_buffer *buf,
|
|
|
|
const unsigned char *data,
|
|
|
|
size_t len)
|
2017-05-22 15:30:59 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (len > (size_t) INT_MAX) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-12-06 09:35:02 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (len > sizeof(buf->data)) {
|
|
|
|
mbedtls_printf(" ! buffer size %u too large (max %u)\n",
|
|
|
|
(unsigned) len, (unsigned) sizeof(buf->data));
|
|
|
|
return -1;
|
2017-05-22 15:30:59 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (sizeof(buf->data) - buf->len < len) {
|
|
|
|
if ((ret = ctx_buffer_flush(buf)) <= 0) {
|
|
|
|
mbedtls_printf("ctx_buffer_flush failed with -%#04x", (unsigned int) -ret);
|
|
|
|
return ret;
|
2019-05-08 16:36:31 +02:00
|
|
|
}
|
2017-05-22 15:30:59 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(buf->data + buf->len, data, len);
|
2017-05-22 15:30:59 +02:00
|
|
|
|
|
|
|
buf->len += len;
|
2023-01-11 14:50:10 +01:00
|
|
|
if (++buf->num_datagrams == 1) {
|
2022-12-04 18:19:59 +01:00
|
|
|
buf->packet_lifetime = elapsed_time();
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return (int) len;
|
2017-05-22 15:30:59 +02:00
|
|
|
}
|
2017-11-02 11:50:28 +01:00
|
|
|
#endif /* MBEDTLS_TIMING_C */
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
static int dispatch_data(mbedtls_net_context *ctx,
|
|
|
|
const unsigned char *data,
|
|
|
|
size_t len)
|
2017-05-22 15:30:59 +02:00
|
|
|
{
|
2019-05-08 16:36:31 +02:00
|
|
|
int ret;
|
2017-11-02 11:50:28 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2017-05-22 15:30:59 +02:00
|
|
|
ctx_buffer *buf = NULL;
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.pack > 0) {
|
|
|
|
if (outbuf[0].ctx == ctx) {
|
2017-11-02 11:50:28 +01:00
|
|
|
buf = &outbuf[0];
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if (outbuf[1].ctx == ctx) {
|
2017-11-02 11:50:28 +01:00
|
|
|
buf = &outbuf[1];
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-10-31 15:10:07 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (buf == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return ctx_buffer_append(buf, data, len);
|
2017-11-02 11:50:28 +01:00
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_TIMING_C */
|
2017-10-31 15:10:07 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
ret = mbedtls_net_send(ctx, data, len);
|
|
|
|
if (ret < 0) {
|
|
|
|
mbedtls_printf("net_send returned -%#04x\n", (unsigned int) -ret);
|
2019-05-08 16:36:31 +02:00
|
|
|
}
|
2023-01-11 14:50:10 +01:00
|
|
|
return ret;
|
2017-10-31 15:10:07 +01:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
typedef struct {
|
2015-06-30 15:40:39 +02:00
|
|
|
mbedtls_net_context *dst;
|
2014-09-06 14:36:46 +02:00
|
|
|
const char *way;
|
2014-09-06 08:14:47 +02:00
|
|
|
const char *type;
|
2014-09-06 14:36:46 +02:00
|
|
|
unsigned len;
|
|
|
|
unsigned char buf[MAX_MSG_SIZE];
|
|
|
|
} packet;
|
|
|
|
|
|
|
|
/* Print packet. Outgoing packets come with a reason (forward, dupl, etc.) */
|
2023-01-11 14:50:10 +01:00
|
|
|
void print_packet(const packet *p, const char *why)
|
2014-09-06 14:36:46 +02:00
|
|
|
{
|
2017-10-31 15:10:07 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (why == NULL) {
|
|
|
|
mbedtls_printf(" %05u dispatch %s %s (%u bytes)\n",
|
|
|
|
elapsed_time(), p->way, p->type, p->len);
|
|
|
|
} else {
|
|
|
|
mbedtls_printf(" %05u dispatch %s %s (%u bytes): %s\n",
|
|
|
|
elapsed_time(), p->way, p->type, p->len, why);
|
|
|
|
}
|
2017-10-31 15:10:07 +01:00
|
|
|
#else
|
2023-01-11 14:50:10 +01:00
|
|
|
if (why == NULL) {
|
|
|
|
mbedtls_printf(" dispatch %s %s (%u bytes)\n",
|
|
|
|
p->way, p->type, p->len);
|
|
|
|
} else {
|
|
|
|
mbedtls_printf(" dispatch %s %s (%u bytes): %s\n",
|
|
|
|
p->way, p->type, p->len, why);
|
|
|
|
}
|
2017-10-31 15:10:07 +01:00
|
|
|
#endif
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
fflush(stdout);
|
2014-09-06 14:36:46 +02:00
|
|
|
}
|
|
|
|
|
2020-03-13 11:11:02 +01:00
|
|
|
/*
|
|
|
|
* In order to test the server's behaviour when receiving a ClientHello after
|
|
|
|
* the connection is established (this could be a hard reset from the client,
|
|
|
|
* but the server must not drop the existing connection before establishing
|
|
|
|
* client reachability, see RFC 6347 Section 4.2.8), we memorize the first
|
|
|
|
* ClientHello we see (which can't have a cookie), then replay it after the
|
|
|
|
* first ApplicationData record - then we're done.
|
|
|
|
*
|
|
|
|
* This is controlled by the inject_clihlo option.
|
|
|
|
*
|
|
|
|
* We want an explicit state and a place to store the packet.
|
|
|
|
*/
|
2020-03-30 12:46:21 +02:00
|
|
|
typedef enum {
|
|
|
|
ICH_INIT, /* haven't seen the first ClientHello yet */
|
|
|
|
ICH_CACHED, /* cached the initial ClientHello */
|
|
|
|
ICH_INJECTED, /* ClientHello already injected, done */
|
|
|
|
} inject_clihlo_state_t;
|
2020-03-13 11:11:02 +01:00
|
|
|
|
2020-03-30 12:46:21 +02:00
|
|
|
static inject_clihlo_state_t inject_clihlo_state;
|
2020-03-13 11:11:02 +01:00
|
|
|
static packet initial_clihlo;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int send_packet(const packet *p, const char *why)
|
2014-09-06 14:36:46 +02:00
|
|
|
{
|
|
|
|
int ret;
|
2015-06-30 15:40:39 +02:00
|
|
|
mbedtls_net_context *dst = p->dst;
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2020-03-13 11:11:02 +01:00
|
|
|
/* save initial ClientHello? */
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.inject_clihlo != 0 &&
|
2020-03-30 12:46:21 +02:00
|
|
|
inject_clihlo_state == ICH_INIT &&
|
2023-01-11 14:50:10 +01:00
|
|
|
strcmp(p->type, "ClientHello") == 0) {
|
|
|
|
memcpy(&initial_clihlo, p, sizeof(packet));
|
2020-03-30 12:46:21 +02:00
|
|
|
inject_clihlo_state = ICH_CACHED;
|
2020-03-13 11:11:02 +01:00
|
|
|
}
|
|
|
|
|
2019-05-24 11:07:42 +02:00
|
|
|
/* insert corrupted CID record? */
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.bad_cid != 0 &&
|
|
|
|
strcmp(p->type, "CID") == 0 &&
|
|
|
|
(rand() % opt.bad_cid) == 0) {
|
2019-05-24 11:07:42 +02:00
|
|
|
unsigned char buf[MAX_MSG_SIZE];
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(buf, p->buf, p->len);
|
2019-05-24 11:07:42 +02:00
|
|
|
|
|
|
|
/* The CID resides at offset 11 in the DTLS record header. */
|
|
|
|
buf[11] ^= 1;
|
2023-01-11 14:50:10 +01:00
|
|
|
print_packet(p, "modified CID");
|
2019-05-24 11:07:42 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = dispatch_data(dst, buf, p->len)) <= 0) {
|
|
|
|
mbedtls_printf(" ! dispatch returned %d\n", ret);
|
|
|
|
return ret;
|
2019-05-24 11:07:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-08 11:24:58 +02:00
|
|
|
/* insert corrupted ApplicationData record? */
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.bad_ad &&
|
|
|
|
strcmp(p->type, "ApplicationData") == 0) {
|
2014-09-08 11:24:58 +02:00
|
|
|
unsigned char buf[MAX_MSG_SIZE];
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(buf, p->buf, p->len);
|
2014-09-08 11:24:58 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (p->len <= 13) {
|
|
|
|
mbedtls_printf(" ! can't corrupt empty AD record");
|
|
|
|
} else {
|
2017-05-26 17:55:07 +02:00
|
|
|
++buf[13];
|
2023-01-11 14:50:10 +01:00
|
|
|
print_packet(p, "corrupted");
|
2017-05-26 17:55:07 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = dispatch_data(dst, buf, p->len)) <= 0) {
|
|
|
|
mbedtls_printf(" ! dispatch returned %d\n", ret);
|
|
|
|
return ret;
|
2014-09-08 11:24:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
print_packet(p, why);
|
|
|
|
if ((ret = dispatch_data(dst, p->buf, p->len)) <= 0) {
|
|
|
|
mbedtls_printf(" ! dispatch returned %d\n", ret);
|
|
|
|
return ret;
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2014-09-06 08:14:47 +02:00
|
|
|
/* Don't duplicate Application Data, only handshake covered */
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.duplicate != 0 &&
|
|
|
|
strcmp(p->type, "ApplicationData") != 0 &&
|
|
|
|
rand() % opt.duplicate == 0) {
|
|
|
|
print_packet(p, "duplicated");
|
|
|
|
|
|
|
|
if ((ret = dispatch_data(dst, p->buf, p->len)) <= 0) {
|
|
|
|
mbedtls_printf(" ! dispatch returned %d\n", ret);
|
|
|
|
return ret;
|
2014-09-06 08:14:47 +02:00
|
|
|
}
|
|
|
|
}
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2020-03-13 11:11:02 +01:00
|
|
|
/* Inject ClientHello after first ApplicationData */
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.inject_clihlo != 0 &&
|
2020-03-30 12:46:21 +02:00
|
|
|
inject_clihlo_state == ICH_CACHED &&
|
2023-01-11 14:50:10 +01:00
|
|
|
strcmp(p->type, "ApplicationData") == 0) {
|
|
|
|
print_packet(&initial_clihlo, "injected");
|
|
|
|
|
|
|
|
if ((ret = dispatch_data(dst, initial_clihlo.buf,
|
|
|
|
initial_clihlo.len)) <= 0) {
|
|
|
|
mbedtls_printf(" ! dispatch returned %d\n", ret);
|
|
|
|
return ret;
|
2020-03-13 11:11:02 +01:00
|
|
|
}
|
|
|
|
|
2020-03-30 12:46:21 +02:00
|
|
|
inject_clihlo_state = ICH_INJECTED;
|
2020-03-13 11:11:02 +01:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2014-09-06 14:36:46 +02:00
|
|
|
}
|
|
|
|
|
2018-08-21 17:39:51 +02:00
|
|
|
#define MAX_DELAYED_MSG 5
|
|
|
|
static size_t prev_len;
|
|
|
|
static packet prev[MAX_DELAYED_MSG];
|
2014-09-23 12:46:33 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
void clear_pending(void)
|
2014-09-23 12:46:33 +02:00
|
|
|
{
|
2023-01-11 14:50:10 +01:00
|
|
|
memset(&prev, 0, sizeof(prev));
|
2018-08-21 17:39:51 +02:00
|
|
|
prev_len = 0;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
void delay_packet(packet *delay)
|
2018-08-21 17:39:51 +02:00
|
|
|
{
|
2023-01-11 14:50:10 +01:00
|
|
|
if (prev_len == MAX_DELAYED_MSG) {
|
2018-08-21 17:39:51 +02:00
|
|
|
return;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2018-08-21 17:39:51 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
memcpy(&prev[prev_len++], delay, sizeof(packet));
|
2018-08-21 17:39:51 +02:00
|
|
|
}
|
|
|
|
|
2023-07-26 16:47:45 +02:00
|
|
|
int send_delayed(void)
|
2018-08-21 17:39:51 +02:00
|
|
|
{
|
|
|
|
uint8_t offset;
|
|
|
|
int ret;
|
2023-01-11 14:50:10 +01:00
|
|
|
for (offset = 0; offset < prev_len; offset++) {
|
|
|
|
ret = send_packet(&prev[offset], "delayed");
|
|
|
|
if (ret != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2018-08-21 17:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
clear_pending();
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2014-09-23 12:46:33 +02:00
|
|
|
}
|
|
|
|
|
2014-09-26 12:08:36 +02:00
|
|
|
/*
|
Fix bug with UDP proxy not forwarding enough
We previously introduced a safety check ensuring that if a datagram had
already been dropped twice, it would no longer be dropped or delayed
after that.
This missed an edge case: if a datagram is dropped once, it can be
delayed any number of times. Since "delay" is not defined in terms of
time (x seconds) but in terms of ordering with respect to other messages
(will be forwarded after the next message is forwarded), depending on
the RNG results this could result in an endless loop where all messages
are delayed until the next, which is itself delayed, etc. and no message
is ever forwarded.
The probability of this happening n times in a row is (1/d)^n, where d
is the value passed as delay=d, so for delay=5 and n=5 it's around 0.03%
which seems small but we still happened on such an occurrence in real
life:
tests/ssl-opt.sh --seed 1625061502 -f 'DTLS proxy: 3d, min handshake, resumption$'
results (according to debug statements added for the investigation) in
the ClientHello of the second handshake being dropped once then delayed
5 times, after which the client stops re-trying and the test fails for
no interesting reason.
Make sure this doesn't happen again by putting a cap on the number of
times we fail to forward a given datagram immediately.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
2021-07-06 12:39:43 +02:00
|
|
|
* Avoid dropping or delaying a packet that was already dropped or delayed
|
|
|
|
* ("held") twice: this only results in uninteresting timeouts. We can't rely
|
|
|
|
* on type to identify packets, since during renegotiation they're all
|
|
|
|
* encrypted. So, rely on size mod 2048 (which is usually just size).
|
|
|
|
*
|
|
|
|
* We only hold packets at the level of entire datagrams, not at the level
|
UDP proxy: Don't attempt to dissect dgram into records when dropping
To prevent dropping the same message over and over again, the UDP proxy
test application programs/test/udp_proxy _logically_ maintains a mapping
from records to the number of times the record has already been dropped,
and stops dropping once a configurable threshold (currently 2) is passed.
However, the actual implementation deviates from this logical view
in two crucial respects:
- To keep the implementation simple and independent of
implementations of suitable map interfaces, it only counts how
many times a record of a given _size_ has been dropped, and
stops dropping further records of that size once the configurable
threshold is passed. Of course, this is not fail-proof, but a
good enough approximation for the proxy, and it allows to use
an inefficient but simple array for the required map.
- The implementation mixes datagram lengths and record lengths:
When deciding whether it is allowed to drop a datagram, it
uses the total datagram size as a lookup index into the map
counting the number of times a package has been dropped. However,
when updating this map, the UDP proxy traverses the datagram
record by record, and updates the mapping at the level of record
lengths.
Apart from this inconsistency, the introduction of the Connection ID
feature leads to yet another problem: The CID length is not part of
the record header but dynamically negotiated during (potentially
encrypted!) handshakes, and it is hence impossible for a passive traffic
analyzer (in this case our UDP proxy) to reliably parse record headers;
especially, it isn't possible to reliably infer the length of a record,
nor to dissect a datagram into records.
The previous implementation of the UDP proxy was not CID-aware and
assumed that the record length would always reside at offsets 11, 12
in the DTLS record header, which would allow it to iterate through
the datagram record by record. As mentioned, this is no longer possible
for CID-based records, and the current implementation can run into
a buffer overflow in this case (because it doesn't validate that
the record length is not larger than what remains in the datagram).
This commit removes the inconsistency in datagram vs. record length
and resolves the buffer overflow issue by not attempting any dissection
of datagrams into records, and instead only counting how often _datagrams_
of a particular size have been dropped.
There is only one practical situation where this makes a difference:
If datagram packing is used by default but disabled on retransmission
(which OpenSSL has been seen to do), it can happen that we drop a
datagram in its initial transmission, then also drop some of its records
when they retransmitted one-by-one afterwards, yet still keeping the
drop-counter at 1 instead of 2. However, even in this situation, we'll
correctly count the number of droppings from that point on and eventually
stop dropping, because the peer will not fall back to using packing
and hence use stable record lengths.
2019-06-04 14:04:28 +02:00
|
|
|
* of records. In particular, if the peer changes the way it packs multiple
|
|
|
|
* records into a single datagram, we don't necessarily count the number of
|
Fix bug with UDP proxy not forwarding enough
We previously introduced a safety check ensuring that if a datagram had
already been dropped twice, it would no longer be dropped or delayed
after that.
This missed an edge case: if a datagram is dropped once, it can be
delayed any number of times. Since "delay" is not defined in terms of
time (x seconds) but in terms of ordering with respect to other messages
(will be forwarded after the next message is forwarded), depending on
the RNG results this could result in an endless loop where all messages
are delayed until the next, which is itself delayed, etc. and no message
is ever forwarded.
The probability of this happening n times in a row is (1/d)^n, where d
is the value passed as delay=d, so for delay=5 and n=5 it's around 0.03%
which seems small but we still happened on such an occurrence in real
life:
tests/ssl-opt.sh --seed 1625061502 -f 'DTLS proxy: 3d, min handshake, resumption$'
results (according to debug statements added for the investigation) in
the ClientHello of the second handshake being dropped once then delayed
5 times, after which the client stops re-trying and the test fails for
no interesting reason.
Make sure this doesn't happen again by putting a cap on the number of
times we fail to forward a given datagram immediately.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
2021-07-06 12:39:43 +02:00
|
|
|
* times a record has been held correctly. However, the only known reason
|
UDP proxy: Don't attempt to dissect dgram into records when dropping
To prevent dropping the same message over and over again, the UDP proxy
test application programs/test/udp_proxy _logically_ maintains a mapping
from records to the number of times the record has already been dropped,
and stops dropping once a configurable threshold (currently 2) is passed.
However, the actual implementation deviates from this logical view
in two crucial respects:
- To keep the implementation simple and independent of
implementations of suitable map interfaces, it only counts how
many times a record of a given _size_ has been dropped, and
stops dropping further records of that size once the configurable
threshold is passed. Of course, this is not fail-proof, but a
good enough approximation for the proxy, and it allows to use
an inefficient but simple array for the required map.
- The implementation mixes datagram lengths and record lengths:
When deciding whether it is allowed to drop a datagram, it
uses the total datagram size as a lookup index into the map
counting the number of times a package has been dropped. However,
when updating this map, the UDP proxy traverses the datagram
record by record, and updates the mapping at the level of record
lengths.
Apart from this inconsistency, the introduction of the Connection ID
feature leads to yet another problem: The CID length is not part of
the record header but dynamically negotiated during (potentially
encrypted!) handshakes, and it is hence impossible for a passive traffic
analyzer (in this case our UDP proxy) to reliably parse record headers;
especially, it isn't possible to reliably infer the length of a record,
nor to dissect a datagram into records.
The previous implementation of the UDP proxy was not CID-aware and
assumed that the record length would always reside at offsets 11, 12
in the DTLS record header, which would allow it to iterate through
the datagram record by record. As mentioned, this is no longer possible
for CID-based records, and the current implementation can run into
a buffer overflow in this case (because it doesn't validate that
the record length is not larger than what remains in the datagram).
This commit removes the inconsistency in datagram vs. record length
and resolves the buffer overflow issue by not attempting any dissection
of datagrams into records, and instead only counting how often _datagrams_
of a particular size have been dropped.
There is only one practical situation where this makes a difference:
If datagram packing is used by default but disabled on retransmission
(which OpenSSL has been seen to do), it can happen that we drop a
datagram in its initial transmission, then also drop some of its records
when they retransmitted one-by-one afterwards, yet still keeping the
drop-counter at 1 instead of 2. However, even in this situation, we'll
correctly count the number of droppings from that point on and eventually
stop dropping, because the peer will not fall back to using packing
and hence use stable record lengths.
2019-06-04 14:04:28 +02:00
|
|
|
* why a peer would change datagram packing is disabling the latter on
|
Fix bug with UDP proxy not forwarding enough
We previously introduced a safety check ensuring that if a datagram had
already been dropped twice, it would no longer be dropped or delayed
after that.
This missed an edge case: if a datagram is dropped once, it can be
delayed any number of times. Since "delay" is not defined in terms of
time (x seconds) but in terms of ordering with respect to other messages
(will be forwarded after the next message is forwarded), depending on
the RNG results this could result in an endless loop where all messages
are delayed until the next, which is itself delayed, etc. and no message
is ever forwarded.
The probability of this happening n times in a row is (1/d)^n, where d
is the value passed as delay=d, so for delay=5 and n=5 it's around 0.03%
which seems small but we still happened on such an occurrence in real
life:
tests/ssl-opt.sh --seed 1625061502 -f 'DTLS proxy: 3d, min handshake, resumption$'
results (according to debug statements added for the investigation) in
the ClientHello of the second handshake being dropped once then delayed
5 times, after which the client stops re-trying and the test fails for
no interesting reason.
Make sure this doesn't happen again by putting a cap on the number of
times we fail to forward a given datagram immediately.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
2021-07-06 12:39:43 +02:00
|
|
|
* retransmission, in which case we'd hold involved records at most
|
|
|
|
* HOLD_MAX + 1 times.
|
|
|
|
*/
|
|
|
|
static unsigned char held[2048] = { 0 };
|
|
|
|
#define HOLD_MAX 2
|
2014-09-26 12:08:36 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int handle_message(const char *way,
|
|
|
|
mbedtls_net_context *dst,
|
|
|
|
mbedtls_net_context *src)
|
2014-09-06 14:36:46 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
packet cur;
|
2014-09-26 12:08:36 +02:00
|
|
|
size_t id;
|
2014-09-06 14:36:46 +02:00
|
|
|
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t delay_idx;
|
2023-01-11 14:50:10 +01:00
|
|
|
char **delay_list;
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t delay_list_len;
|
|
|
|
|
2014-09-08 16:39:08 +02:00
|
|
|
/* receive packet */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_net_recv(src, cur.buf, sizeof(cur.buf))) <= 0) {
|
|
|
|
mbedtls_printf(" ! mbedtls_net_recv returned %d\n", ret);
|
|
|
|
return ret;
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2014-09-06 14:36:46 +02:00
|
|
|
cur.len = ret;
|
2023-01-11 14:50:10 +01:00
|
|
|
cur.type = msg_type(cur.buf, cur.len);
|
2014-09-06 14:36:46 +02:00
|
|
|
cur.way = way;
|
2014-09-24 17:42:09 +02:00
|
|
|
cur.dst = dst;
|
2023-01-11 14:50:10 +01:00
|
|
|
print_packet(&cur, NULL);
|
2014-09-06 14:36:46 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
id = cur.len % sizeof(held);
|
2014-09-26 12:08:36 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (strcmp(way, "S <- C") == 0) {
|
2018-08-17 14:33:41 +02:00
|
|
|
delay_list = opt.delay_cli;
|
|
|
|
delay_list_len = opt.delay_cli_cnt;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else {
|
2018-08-17 14:33:41 +02:00
|
|
|
delay_list = opt.delay_srv;
|
|
|
|
delay_list_len = opt.delay_srv_cnt;
|
|
|
|
}
|
2018-08-28 11:09:47 +02:00
|
|
|
|
2018-08-17 14:33:41 +02:00
|
|
|
/* Check if message type is in the list of messages
|
|
|
|
* that should be delayed */
|
2023-01-11 14:50:10 +01:00
|
|
|
for (delay_idx = 0; delay_idx < delay_list_len; delay_idx++) {
|
|
|
|
if (delay_list[delay_idx] == NULL) {
|
2018-08-17 14:33:41 +02:00
|
|
|
continue;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2018-08-17 14:33:41 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (strcmp(delay_list[delay_idx], cur.type) == 0) {
|
2018-08-17 14:33:41 +02:00
|
|
|
/* Delay message */
|
2023-01-11 14:50:10 +01:00
|
|
|
delay_packet(&cur);
|
2018-08-17 14:33:41 +02:00
|
|
|
|
|
|
|
/* Remove entry from list */
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_free(delay_list[delay_idx]);
|
2018-08-17 14:33:41 +02:00
|
|
|
delay_list[delay_idx] = NULL;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2018-08-17 14:33:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-06 14:49:52 +02:00
|
|
|
/* do we want to drop, delay, or forward it? */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((opt.mtu != 0 &&
|
|
|
|
cur.len > (unsigned) opt.mtu) ||
|
|
|
|
(opt.drop != 0 &&
|
|
|
|
strcmp(cur.type, "CID") != 0 &&
|
|
|
|
strcmp(cur.type, "ApplicationData") != 0 &&
|
|
|
|
!(opt.protect_hvr &&
|
|
|
|
strcmp(cur.type, "HelloVerifyRequest") == 0) &&
|
|
|
|
cur.len != (size_t) opt.protect_len &&
|
|
|
|
held[id] < HOLD_MAX &&
|
|
|
|
rand() % opt.drop == 0)) {
|
Fix bug with UDP proxy not forwarding enough
We previously introduced a safety check ensuring that if a datagram had
already been dropped twice, it would no longer be dropped or delayed
after that.
This missed an edge case: if a datagram is dropped once, it can be
delayed any number of times. Since "delay" is not defined in terms of
time (x seconds) but in terms of ordering with respect to other messages
(will be forwarded after the next message is forwarded), depending on
the RNG results this could result in an endless loop where all messages
are delayed until the next, which is itself delayed, etc. and no message
is ever forwarded.
The probability of this happening n times in a row is (1/d)^n, where d
is the value passed as delay=d, so for delay=5 and n=5 it's around 0.03%
which seems small but we still happened on such an occurrence in real
life:
tests/ssl-opt.sh --seed 1625061502 -f 'DTLS proxy: 3d, min handshake, resumption$'
results (according to debug statements added for the investigation) in
the ClientHello of the second handshake being dropped once then delayed
5 times, after which the client stops re-trying and the test fails for
no interesting reason.
Make sure this doesn't happen again by putting a cap on the number of
times we fail to forward a given datagram immediately.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
2021-07-06 12:39:43 +02:00
|
|
|
++held[id];
|
2023-01-11 14:50:10 +01:00
|
|
|
} else if ((opt.delay_ccs == 1 &&
|
|
|
|
strcmp(cur.type, "ChangeCipherSpec") == 0) ||
|
|
|
|
(opt.delay != 0 &&
|
|
|
|
strcmp(cur.type, "CID") != 0 &&
|
|
|
|
strcmp(cur.type, "ApplicationData") != 0 &&
|
|
|
|
!(opt.protect_hvr &&
|
|
|
|
strcmp(cur.type, "HelloVerifyRequest") == 0) &&
|
|
|
|
cur.len != (size_t) opt.protect_len &&
|
|
|
|
held[id] < HOLD_MAX &&
|
|
|
|
rand() % opt.delay == 0)) {
|
Fix bug with UDP proxy not forwarding enough
We previously introduced a safety check ensuring that if a datagram had
already been dropped twice, it would no longer be dropped or delayed
after that.
This missed an edge case: if a datagram is dropped once, it can be
delayed any number of times. Since "delay" is not defined in terms of
time (x seconds) but in terms of ordering with respect to other messages
(will be forwarded after the next message is forwarded), depending on
the RNG results this could result in an endless loop where all messages
are delayed until the next, which is itself delayed, etc. and no message
is ever forwarded.
The probability of this happening n times in a row is (1/d)^n, where d
is the value passed as delay=d, so for delay=5 and n=5 it's around 0.03%
which seems small but we still happened on such an occurrence in real
life:
tests/ssl-opt.sh --seed 1625061502 -f 'DTLS proxy: 3d, min handshake, resumption$'
results (according to debug statements added for the investigation) in
the ClientHello of the second handshake being dropped once then delayed
5 times, after which the client stops re-trying and the test fails for
no interesting reason.
Make sure this doesn't happen again by putting a cap on the number of
times we fail to forward a given datagram immediately.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
2021-07-06 12:39:43 +02:00
|
|
|
++held[id];
|
2023-01-11 14:50:10 +01:00
|
|
|
delay_packet(&cur);
|
|
|
|
} else {
|
2014-09-06 14:49:52 +02:00
|
|
|
/* forward and possibly duplicate */
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = send_packet(&cur, "forwarded")) != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2014-09-06 14:36:46 +02:00
|
|
|
|
2018-08-21 17:39:51 +02:00
|
|
|
/* send previously delayed messages if any */
|
|
|
|
ret = send_delayed();
|
2023-01-11 14:50:10 +01:00
|
|
|
if (ret != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2014-09-06 14:36:46 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
return 0;
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
int main(int argc, char *argv[])
|
2014-09-04 14:55:28 +02:00
|
|
|
{
|
2018-04-29 22:58:53 +02:00
|
|
|
int ret = 1;
|
|
|
|
int exit_code = MBEDTLS_EXIT_FAILURE;
|
2018-08-17 14:33:41 +02:00
|
|
|
uint8_t delay_idx;
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2015-06-30 15:40:39 +02:00
|
|
|
mbedtls_net_context listen_fd, client_fd, server_fd;
|
2017-11-02 11:50:28 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2017-05-22 15:30:59 +02:00
|
|
|
struct timeval tm;
|
2017-11-02 11:50:28 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct timeval *tm_ptr = NULL;
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
int nb_fds;
|
|
|
|
fd_set read_fds;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_net_init(&listen_fd);
|
|
|
|
mbedtls_net_init(&client_fd);
|
|
|
|
mbedtls_net_init(&server_fd);
|
2015-06-30 15:40:39 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
get_options(argc, argv);
|
2014-09-20 18:06:23 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Decisions to drop/delay/duplicate packets are pseudo-random: dropping
|
|
|
|
* exactly 1 in N packets would lead to problems when a flight has exactly
|
|
|
|
* N packets: the same packet would be dropped on every resend.
|
|
|
|
*
|
|
|
|
* In order to be able to reproduce problems reliably, the seed may be
|
|
|
|
* specified explicitly.
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.seed == 0) {
|
2022-04-05 21:39:43 +02:00
|
|
|
#if defined(MBEDTLS_HAVE_TIME)
|
2023-01-11 14:50:10 +01:00
|
|
|
opt.seed = (unsigned int) mbedtls_time(NULL);
|
2022-04-05 21:39:43 +02:00
|
|
|
#else
|
|
|
|
opt.seed = 1;
|
|
|
|
#endif /* MBEDTLS_HAVE_TIME */
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" . Pseudo-random seed: %u\n", opt.seed);
|
2014-09-20 18:06:23 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
srand(opt.seed);
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
/*
|
2014-09-06 08:07:45 +02:00
|
|
|
* 0. "Connect" to the server
|
2014-09-04 14:55:28 +02:00
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" . Connect to server on UDP/%s/%s ...",
|
|
|
|
opt.server_addr, opt.server_port);
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
if ((ret = mbedtls_net_connect(&server_fd, opt.server_addr, opt.server_port,
|
|
|
|
MBEDTLS_NET_PROTO_UDP)) != 0) {
|
|
|
|
mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret);
|
2014-09-04 14:55:28 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" ok\n");
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 1. Setup the "listening" UDP socket
|
|
|
|
*/
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" . Bind on UDP/%s/%s ...",
|
|
|
|
opt.listen_addr, opt.listen_port);
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
if ((ret = mbedtls_net_bind(&listen_fd, opt.listen_addr, opt.listen_port,
|
|
|
|
MBEDTLS_NET_PROTO_UDP)) != 0) {
|
|
|
|
mbedtls_printf(" failed\n ! mbedtls_net_bind returned %d\n\n", ret);
|
2014-09-04 14:55:28 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" ok\n");
|
2014-09-04 14:55:28 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 2. Wait until a client connects
|
|
|
|
*/
|
2014-09-23 12:46:33 +02:00
|
|
|
accept:
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_net_free(&client_fd);
|
2015-07-01 01:28:24 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" . Waiting for a remote connection ...");
|
|
|
|
fflush(stdout);
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = mbedtls_net_accept(&listen_fd, &client_fd,
|
|
|
|
NULL, 0, NULL)) != 0) {
|
|
|
|
mbedtls_printf(" failed\n ! mbedtls_net_accept returned %d\n\n", ret);
|
2014-09-04 14:55:28 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_printf(" ok\n");
|
2014-09-23 12:46:33 +02:00
|
|
|
|
2014-09-04 14:55:28 +02:00
|
|
|
/*
|
|
|
|
* 3. Forward packets forever (kill the process to terminate it)
|
|
|
|
*/
|
2014-10-01 00:56:03 +02:00
|
|
|
clear_pending();
|
2023-01-11 14:50:10 +01:00
|
|
|
memset(held, 0, sizeof(held));
|
2014-10-01 00:56:03 +02:00
|
|
|
|
2015-06-30 15:40:39 +02:00
|
|
|
nb_fds = client_fd.fd;
|
2023-01-11 14:50:10 +01:00
|
|
|
if (nb_fds < server_fd.fd) {
|
2015-06-30 15:40:39 +02:00
|
|
|
nb_fds = server_fd.fd;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
|
|
|
if (nb_fds < listen_fd.fd) {
|
2015-06-30 15:40:39 +02:00
|
|
|
nb_fds = listen_fd.fd;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2014-09-23 12:46:33 +02:00
|
|
|
++nb_fds;
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2017-10-31 15:10:07 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.pack > 0) {
|
2017-05-22 15:30:59 +02:00
|
|
|
outbuf[0].ctx = &server_fd;
|
|
|
|
outbuf[0].description = "S <- C";
|
|
|
|
outbuf[0].num_datagrams = 0;
|
|
|
|
outbuf[0].len = 0;
|
|
|
|
|
|
|
|
outbuf[1].ctx = &client_fd;
|
|
|
|
outbuf[1].description = "S -> C";
|
|
|
|
outbuf[1].num_datagrams = 0;
|
|
|
|
outbuf[1].len = 0;
|
|
|
|
}
|
2017-10-31 15:10:07 +01:00
|
|
|
#endif /* MBEDTLS_TIMING_C */
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
while (1) {
|
2017-11-02 11:50:28 +01:00
|
|
|
#if defined(MBEDTLS_TIMING_C)
|
2023-01-11 14:50:10 +01:00
|
|
|
if (opt.pack > 0) {
|
2017-11-02 11:50:28 +01:00
|
|
|
unsigned max_wait_server, max_wait_client, max_wait;
|
2023-01-11 14:50:10 +01:00
|
|
|
max_wait_server = ctx_buffer_time_remaining(&outbuf[0]);
|
|
|
|
max_wait_client = ctx_buffer_time_remaining(&outbuf[1]);
|
2017-11-02 11:50:28 +01:00
|
|
|
|
|
|
|
max_wait = (unsigned) -1;
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (max_wait_server == 0) {
|
|
|
|
ctx_buffer_flush(&outbuf[0]);
|
|
|
|
} else {
|
2017-11-02 11:50:28 +01:00
|
|
|
max_wait = max_wait_server;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-11-02 11:50:28 +01:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (max_wait_client == 0) {
|
|
|
|
ctx_buffer_flush(&outbuf[1]);
|
|
|
|
} else {
|
|
|
|
if (max_wait_client < max_wait) {
|
2017-11-02 11:50:28 +01:00
|
|
|
max_wait = max_wait_client;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2017-11-02 11:50:28 +01:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (max_wait != (unsigned) -1) {
|
2017-11-02 11:50:28 +01:00
|
|
|
tm.tv_sec = max_wait / 1000;
|
2023-01-11 14:50:10 +01:00
|
|
|
tm.tv_usec = (max_wait % 1000) * 1000;
|
2017-11-02 11:50:28 +01:00
|
|
|
|
|
|
|
tm_ptr = &tm;
|
2023-01-11 14:50:10 +01:00
|
|
|
} else {
|
2017-11-02 11:50:28 +01:00
|
|
|
tm_ptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_TIMING_C */
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
FD_ZERO(&read_fds);
|
|
|
|
FD_SET(server_fd.fd, &read_fds);
|
|
|
|
FD_SET(client_fd.fd, &read_fds);
|
|
|
|
FD_SET(listen_fd.fd, &read_fds);
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if ((ret = select(nb_fds, &read_fds, NULL, NULL, tm_ptr)) < 0) {
|
|
|
|
perror("select");
|
2014-09-04 14:55:28 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (FD_ISSET(listen_fd.fd, &read_fds)) {
|
2014-09-23 12:46:33 +02:00
|
|
|
goto accept;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2014-09-23 12:46:33 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (FD_ISSET(client_fd.fd, &read_fds)) {
|
|
|
|
if ((ret = handle_message("S <- C",
|
|
|
|
&server_fd, &client_fd)) != 0) {
|
2014-10-01 00:56:03 +02:00
|
|
|
goto accept;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
if (FD_ISSET(server_fd.fd, &read_fds)) {
|
|
|
|
if ((ret = handle_message("S -> C",
|
|
|
|
&client_fd, &server_fd)) != 0) {
|
2014-10-01 00:56:03 +02:00
|
|
|
goto accept;
|
2023-01-11 14:50:10 +01:00
|
|
|
}
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
2017-05-22 15:30:59 +02:00
|
|
|
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2018-04-29 22:58:53 +02:00
|
|
|
exit_code = MBEDTLS_EXIT_SUCCESS;
|
|
|
|
|
2014-09-04 14:55:28 +02:00
|
|
|
exit:
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#ifdef MBEDTLS_ERROR_C
|
2023-01-11 14:50:10 +01:00
|
|
|
if (exit_code != MBEDTLS_EXIT_SUCCESS) {
|
2014-09-04 14:55:28 +02:00
|
|
|
char error_buf[100];
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_strerror(ret, error_buf, 100);
|
|
|
|
mbedtls_printf("Last error was: -0x%04X - %s\n\n", (unsigned int) -ret, error_buf);
|
|
|
|
fflush(stdout);
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
for (delay_idx = 0; delay_idx < MAX_DELAYED_HS; delay_idx++) {
|
|
|
|
mbedtls_free(opt.delay_cli[delay_idx]);
|
|
|
|
mbedtls_free(opt.delay_srv[delay_idx]);
|
2018-08-17 14:33:41 +02:00
|
|
|
}
|
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_net_free(&client_fd);
|
|
|
|
mbedtls_net_free(&server_fd);
|
|
|
|
mbedtls_net_free(&listen_fd);
|
2014-09-04 14:55:28 +02:00
|
|
|
|
2023-01-11 14:50:10 +01:00
|
|
|
mbedtls_exit(exit_code);
|
2014-09-04 14:55:28 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_NET_C */
|