From ca0b9636a52f779b9eff91dd4324dc819097873d Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:44:47 -0700 Subject: [PATCH 01/10] F-5002 - https://fenrir.wolfssl.com/finding/5002 - Reject handshake when issuer name rendering returns NULL --- examples/notification-demo/log_server/log_server.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index c90d281..9f36dd8 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -473,6 +473,10 @@ static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { issuerHash = wolfSSL_X509_issuer_name_hash(store->current_cert); issuerName = wolfSSL_X509_NAME_oneline( wolfSSL_X509_get_issuer_name(store->current_cert), 0, 0); + if (issuerName == NULL) { + fprintf(stderr, "ERROR: %s L%d null issuer name.\n", __FILE__,__LINE__); + return WOLFSSL_FAILURE; + } #ifdef DEBUG_TLS subjectCN = wolfSSL_X509_get_subjectCN(store->current_cert); From ea0a82cfafc714f777e01fd8c4eb5cc5c9d57a7c Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:45:57 -0700 Subject: [PATCH 02/10] F-5779 - https://fenrir.wolfssl.com/finding/5779 - Free X509 name strings on every verify callback return path --- .../notification-demo/log_server/log_server.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index 9f36dd8..b9874b1 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -420,11 +420,11 @@ struct log_server_data { static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { struct log_server_data *app_data = NULL; - const char* issuerName = NULL; + char* issuerName = NULL; unsigned long issuerHash = 0; #if defined(DEBUG_TLS) && defined(OPENSSL_EXTRA) const char *subjectCN; - const char* subjectName; + char* subjectName = NULL; unsigned long subjectHash = 0; #endif struct ca_cert *ca_certs_i; @@ -501,11 +501,23 @@ static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { } if (app_data->issuer_cert == NULL) { fprintf(stderr, "ERROR: %s L%d app_data->issuer_cert NULL.\n",__FILE__,__LINE__); +#ifdef OPENSSL_EXTRA + XFREE(issuerName, NULL, DYNAMIC_TYPE_OPENSSL); + #ifdef DEBUG_TLS + XFREE(subjectName, NULL, DYNAMIC_TYPE_OPENSSL); + #endif +#endif return WOLFSSL_FAILURE; } app_data->error_code = 0; +#ifdef OPENSSL_EXTRA + XFREE(issuerName, NULL, DYNAMIC_TYPE_OPENSSL); + #ifdef DEBUG_TLS + XFREE(subjectName, NULL, DYNAMIC_TYPE_OPENSSL); + #endif +#endif return WOLFSSL_SUCCESS; } From 4a3671537a6ca2d067944a8fcb457bb7e1c15aec Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:46:28 -0700 Subject: [PATCH 03/10] F-5712 - https://fenrir.wolfssl.com/finding/5712 - Strip control bytes from peer certificate strings before logging --- .../notification-demo/log_server/log_server.c | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index b9874b1..2ed4aa0 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -417,6 +417,27 @@ struct log_server_data { int error_code; }; +#if defined(DEBUG_TLS) && defined(OPENSSL_EXTRA) +/* certificate DN strings are peer-controlled; drop control bytes before logging. */ +static const char *sanitize_log_str(const char *in, char *out, size_t outsz) { + size_t i; + unsigned char c; + + if (in == NULL) + return "(null)"; + if (outsz == 0) + return out; + for (i = 0; (i + 1 < outsz) && (in[i] != '\0'); ++i) { + c = (unsigned char)in[i]; + if ((c < 0x20) || (c == 0x7f)) + out[i] = '?'; + else + out[i] = (char)c; + } + out[i] = '\0'; + return out; +} +#endif static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { struct log_server_data *app_data = NULL; @@ -426,6 +447,7 @@ static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { const char *subjectCN; char* subjectName = NULL; unsigned long subjectHash = 0; + char subjectCN_buf[256], subjectName_buf[256], issuerName_buf[256]; #endif struct ca_cert *ca_certs_i; @@ -484,8 +506,11 @@ static int myVerifyCheck(int preverify, WOLFSSL_X509_STORE_CTX* store) { subjectName = wolfSSL_X509_NAME_oneline( wolfSSL_X509_get_subject_name(store->current_cert), 0, 0); fprintf(stderr, "CN=%s subjectName->name=\"%s\" subject_hash=%lu\n", - subjectCN, subjectName, subjectHash); - fprintf(stderr, "issuerName->name=\"%s\" issuer_hash=%lu\n", issuerName, issuerHash); + sanitize_log_str(subjectCN, subjectCN_buf, sizeof subjectCN_buf), + sanitize_log_str(subjectName, subjectName_buf, sizeof subjectName_buf), + subjectHash); + fprintf(stderr, "issuerName->name=\"%s\" issuer_hash=%lu\n", + sanitize_log_str(issuerName, issuerName_buf, sizeof issuerName_buf), issuerHash); #endif #endif From 979181eaa54cab3f5696784547e28df47ea23d52 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:48:00 -0700 Subject: [PATCH 04/10] F-5778 - https://fenrir.wolfssl.com/finding/5778 - Evict the entry at offset zero when the circular log wraps --- .../notification-demo/log_server/log_server.c | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index 2ed4aa0..3e7b1d6 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -315,6 +315,10 @@ wolfsentry_errcode_t circlog_enqueue_one(size_t msg_len, char **msg_buf) { if (new_ent_size > circlog_size) WOLFSENTRY_ERROR_RETURN(INVALID_ARG); + /* reset a fully drained queue so a wrap cannot strand a stale head. */ + if (circlog_head == circlog_tail) + circlog_head = circlog_tail = 0; + if (circlog_tail + new_ent_size > circlog_size) { /* if the new ent will wrap, old ents need to be cleared out to the end, and a skip ent inserted. */ if (circlog_tail + circlog_ent_size_from_msg_len(0) < circlog_size) { @@ -342,7 +346,8 @@ wolfsentry_errcode_t circlog_enqueue_one(size_t msg_len, char **msg_buf) { * the =, circlog_tail could be incremented below to equal circlog_head, * which is defined to be an empty queue. */ - while ((circlog_head > new_msg_start) && + while ((circlog_nents > 0) && + (circlog_head >= new_msg_start) && (circlog_head <= new_msg_start + new_ent_size)) { ret = circlog_dequeue_one(NULL); @@ -350,6 +355,10 @@ wolfsentry_errcode_t circlog_enqueue_one(size_t msg_len, char **msg_buf) { return ret; } + /* if eviction drained the queue, the new entry alone defines the head. */ + if (circlog_nents == 0) + circlog_head = new_msg_start; + new_ent = (struct circlog_message *)(void *)(circlog + new_msg_start); ret = wolfsentry_time_now_plus_delta(global_wolfsentry, 0 /* td */, &new_ent->when); new_ent->len = (uint16_t)msg_len; @@ -1518,6 +1527,47 @@ int main(int argc, char **argv) { fprintf(stderr,"circlog_head=%zu circlog_tail=%zu\n",circlog_head,circlog_tail); } + + if (circlog != NULL) { + char *wrap_buf; + struct circlog_message *wrap_msg; + size_t wrap_filled, wrap_reachable; + static const char wrap_s[] = "wrap eviction regression probe entry."; + size_t wrap_ent = circlog_ent_size_from_msg_len(strlen(wrap_s)); + + if ((circlog_reset() >= 0) && ((wrap_ent * 2) <= circlog_size)) { + wrap_filled = 0; + while ((circlog_tail + wrap_ent) <= circlog_size) { + ret = circlog_enqueue_one(strlen(wrap_s), &wrap_buf); + if (ret < 0) { + fprintf(stderr, "ERROR: %s L%d circlog failed: " WOLFSENTRY_ERROR_FMT "\n", __FILE__, __LINE__, WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(1); + } + memcpy(wrap_buf, wrap_s, strlen(wrap_s)); + ++wrap_filled; + } + + ret = circlog_enqueue_one(strlen(wrap_s), &wrap_buf); + if (ret < 0) { + fprintf(stderr, "ERROR: %s L%d circlog failed: " WOLFSENTRY_ERROR_FMT "\n", __FILE__, __LINE__, WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(1); + } + memcpy(wrap_buf, wrap_s, strlen(wrap_s)); + + wrap_reachable = 0; + wrap_msg = NULL; + while (circlog_iterate(&wrap_msg) >= 0) + ++wrap_reachable; + + if (circlog_nents != wrap_reachable) { + fprintf(stderr, "ERROR: %s L%d circlog nents=%zu disagrees with reachable=%zu after wrap (filled=%zu).\n", + __FILE__, __LINE__, circlog_nents, wrap_reachable, wrap_filled); + exit(1); + } + + fprintf(stderr, "circlog wrap-eviction check OK: nents=%zu reachable=%zu\n", circlog_nents, wrap_reachable); + } + } #endif /* CIRCLOG_UNIT_TEST */ log_server_init(); From c1f68ebe401c69cf7c47d8fe3cb91a0d87c610b4 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:48:11 -0700 Subject: [PATCH 05/10] F-4704 - https://fenrir.wolfssl.com/finding/4704 - Skip route dispatch at shutdown when no rule route was checked out --- examples/notification-demo/log_server/log_server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index 3e7b1d6..96d7bca 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -1962,7 +1962,8 @@ int main(int argc, char **argv) { } #endif - if (! (wolfsentry_data->action_results & WOLFSENTRY_ACTION_RES_FALLTHROUGH)) { + if ((! (wolfsentry_data->action_results & WOLFSENTRY_ACTION_RES_FALLTHROUGH)) && + (wolfsentry_data->rule_route != NULL)) { wolfsentry_action_res_t action_results; if (transaction_successful) { ret = wolfsentry_route_event_dispatch_by_route(WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(global_wolfsentry, global_thread), From aae0a26b5a3fa856490e58a5b206650e5ac1af94 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:48:30 -0700 Subject: [PATCH 06/10] F-4821 - https://fenrir.wolfssl.com/finding/4821 - Reject circlog-size values that overflow size_t before allocating --- examples/notification-demo/log_server/log_server.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index 96d7bca..6d92ace 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -1467,6 +1467,12 @@ int main(int argc, char **argv) { exit(1); } + if (circlog_size_uint64 > (uint64_t)SIZE_MAX) { + fprintf(stderr, "ERROR: \"circlog-size\" value %llu exceeds SIZE_MAX on this ABI\n", + (unsigned long long)circlog_size_uint64); + exit(1); + } + ret = circlog_init((size_t)circlog_size_uint64); if (ret < 0) { fprintf(stderr, "ERROR: circlog_init() failed: " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); From 298fb3fbbad82ae87df3eff28ab607fc37166200 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:48:54 -0700 Subject: [PATCH 07/10] F-5073 - https://fenrir.wolfssl.com/finding/5073 - Stop truncating the config file size returned by ftell --- examples/notification-demo/log_server/log_server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/notification-demo/log_server/log_server.c b/examples/notification-demo/log_server/log_server.c index 6d92ace..2c3a3dc 100644 --- a/examples/notification-demo/log_server/log_server.c +++ b/examples/notification-demo/log_server/log_server.c @@ -1170,6 +1170,7 @@ static int http_write_header(WOLFSSL *ssl, char *http_buf, size_t http_buf_size, #ifndef NO_FILESYSTEM /* reads file size, allocates buffer, reads into buffer, returns buffer */ #include +#define LOAD_FILE_MAX_SZ (64 * 1024 * 1024) static int load_file(const char* fname, unsigned char** buf, size_t* bufLen) { int ret; @@ -1192,9 +1193,9 @@ static int load_file(const char* fname, unsigned char** buf, size_t* bufLen) } fseek(lFile, 0, SEEK_END); - fileSz = (int)ftell(lFile); + fileSz = ftell(lFile); rewind(lFile); - if (fileSz > 0) { + if ((fileSz > 0) && (fileSz <= (long int)LOAD_FILE_MAX_SZ)) { *bufLen = (size_t)fileSz; *buf = (unsigned char*)malloc(*bufLen); if (*buf == NULL) { From 68261169f467005d590d32aacdbf77a9ee9f679d Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:49:06 -0700 Subject: [PATCH 08/10] F-5008 - https://fenrir.wolfssl.com/finding/5008 - Check buffer space before writing the decision list separator --- examples/notification-demo/log_server/sentry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/notification-demo/log_server/sentry.c b/examples/notification-demo/log_server/sentry.c index e415539..22eea81 100644 --- a/examples/notification-demo/log_server/sentry.c +++ b/examples/notification-demo/log_server/sentry.c @@ -551,10 +551,10 @@ static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( if ((res_string = wolfsentry_action_res_assoc_by_flag(*action_results, res_bit)) != NULL) { ++n_res_bits; if (n_res_bits > 1) { + if (msgbuf_space_left <= 0) + WOLFSENTRY_ERROR_RETURN(BUFFER_TOO_SMALL); *msgbuf_ptr++ = ','; --msgbuf_space_left; - if (msgbuf_space_left < 0) - WOLFSENTRY_ERROR_RETURN(BUFFER_TOO_SMALL); } msgbuf_len = snprintf(msgbuf_ptr, (size_t)msgbuf_space_left, "\"%s\"", res_string); msgbuf_space_left -= msgbuf_len; From 5a18bcbda8cd7df255c6cdcbdd13485fe8faf898 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 21 Oct 2026 14:50:00 -0700 Subject: [PATCH 09/10] F-4763 - https://fenrir.wolfssl.com/finding/4763 - Escape event and address-family labels written into the circular log JSON --- .../notification-demo/log_server/sentry.c | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/examples/notification-demo/log_server/sentry.c b/examples/notification-demo/log_server/sentry.c index 22eea81..e6c229a 100644 --- a/examples/notification-demo/log_server/sentry.c +++ b/examples/notification-demo/log_server/sentry.c @@ -320,6 +320,39 @@ static int wolfSentry_NetworkFilterCallback( } +/* labels come from loaded config; escape them so they cannot break the JSON record. */ +static const char *json_escape_label(const char *in, char *out, size_t outsz) { + size_t i, o; + unsigned char c; + + if (in == NULL) + return ""; + if (outsz == 0) + return ""; + o = 0; + for (i = 0; in[i] != '\0'; ++i) { + c = (unsigned char)in[i]; + if ((c == '"') || (c == '\\')) { + if ((o + 2) >= outsz) + break; + out[o++] = '\\'; + out[o++] = (char)c; + } + else if ((c < 0x20) || (c == 0x7f)) { + if ((o + 1) >= outsz) + break; + out[o++] = '?'; + } + else { + if ((o + 1) >= outsz) + break; + out[o++] = (char)c; + } + } + out[o] = '\0'; + return out; +} + static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( WOLFSENTRY_CONTEXT_ARGS_IN, const struct wolfsentry_action *action, @@ -353,6 +386,9 @@ static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( char msgbuf[1024], *msgbuf_ptr = msgbuf; int msgbuf_space_left = (int)sizeof msgbuf; int msgbuf_len; + char trigger_label_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; + char parent_label_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; + char family_name_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; (void)handler_arg; (void)route_table; @@ -452,11 +488,11 @@ static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( "{ \"timestamp\" : \"%s\", \"action\" : \"%s\", \"trigger\" : %s%s%s, \"parent\" : %s%s%s, \"rule-id\" : " WOLFSENTRY_ENT_ID_FMT ", \"rule-hitcount\" : " WOLFSENTRY_HITCOUNT_FMT ", \"af\" : \"%s\", \"proto\" : %d, \"remote\" : { \"address\" : \"", timebuf, wolfsentry_action_get_label(action), - trigger_event ? "\"" : "", trigger_event ? wolfsentry_event_get_label(trigger_event) : "null", trigger_event ? "\"" : "", - trigger_route_exports.parent_event_label ? "\"" : "", trigger_route_exports.parent_event_label ? trigger_route_exports.parent_event_label : "null", trigger_route_exports.parent_event_label ? "\"" : "", + trigger_event ? "\"" : "", trigger_event ? json_escape_label(wolfsentry_event_get_label(trigger_event), trigger_label_buf, sizeof trigger_label_buf) : "null", trigger_event ? "\"" : "", + trigger_route_exports.parent_event_label ? "\"" : "", trigger_route_exports.parent_event_label ? json_escape_label(trigger_route_exports.parent_event_label, parent_label_buf, sizeof parent_label_buf) : "null", trigger_route_exports.parent_event_label ? "\"" : "", wolfsentry_get_object_id(rule_route), rule_route_exports.meta.hit_count, - family_name, + json_escape_label(family_name, family_name_buf, sizeof family_name_buf), trigger_route_exports.sa_proto); msgbuf_space_left -= msgbuf_len; From 3845490682f821b62a62c1e40a632f19a177a14e Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Fri, 23 Oct 2026 18:09:36 -0700 Subject: [PATCH 10/10] F-4763 - https://fenrir.wolfssl.com/finding/4763 - Escape the action label written into the circular log JSON --- examples/notification-demo/log_server/sentry.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/notification-demo/log_server/sentry.c b/examples/notification-demo/log_server/sentry.c index e6c229a..ff3a23b 100644 --- a/examples/notification-demo/log_server/sentry.c +++ b/examples/notification-demo/log_server/sentry.c @@ -386,6 +386,7 @@ static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( char msgbuf[1024], *msgbuf_ptr = msgbuf; int msgbuf_space_left = (int)sizeof msgbuf; int msgbuf_len; + char action_label_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; char trigger_label_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; char parent_label_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; char family_name_buf[(WOLFSENTRY_MAX_LABEL_BYTES * 2) + 1]; @@ -487,7 +488,7 @@ static wolfsentry_errcode_t wolfsentry_notify_via_UDP_JSON( (size_t)msgbuf_space_left, "{ \"timestamp\" : \"%s\", \"action\" : \"%s\", \"trigger\" : %s%s%s, \"parent\" : %s%s%s, \"rule-id\" : " WOLFSENTRY_ENT_ID_FMT ", \"rule-hitcount\" : " WOLFSENTRY_HITCOUNT_FMT ", \"af\" : \"%s\", \"proto\" : %d, \"remote\" : { \"address\" : \"", timebuf, - wolfsentry_action_get_label(action), + json_escape_label(wolfsentry_action_get_label(action), action_label_buf, sizeof action_label_buf), trigger_event ? "\"" : "", trigger_event ? json_escape_label(wolfsentry_event_get_label(trigger_event), trigger_label_buf, sizeof trigger_label_buf) : "null", trigger_event ? "\"" : "", trigger_route_exports.parent_event_label ? "\"" : "", trigger_route_exports.parent_event_label ? json_escape_label(trigger_route_exports.parent_event_label, parent_label_buf, sizeof parent_label_buf) : "null", trigger_route_exports.parent_event_label ? "\"" : "", wolfsentry_get_object_id(rule_route),