CVE-2023-41102: Missing Release of Memory after Effective Lifetime (CWE-401)
value: An issue was discovered in the captive portal in OpenNDS before version 10.1.3. It has multiple memory leaks due to not freeing up allocated memory. This may lead to a Denial-of-Service condition due to the consumption of all available memory. Affected OpenNDS before version 10.1.3 fixed in OpenWrt master and OpenWrt 23.05 on 23. November by updating OpenNDS to version 10.2.0.
CWE description: The product does not sufficiently track and release allocated memory after it has been used, which slowly consumes remaining memory.
CVSS v3 base score: 7.5
Published: 2023-11-17T06:15Z
Repository: https://github.com/openNDS/openNDS
Language: C
Files changed: src/client_list.c, src/http_microhttpd.c
Commit date: 2023-09-16 11:51:21 +0100
Commit message: Fix - memory leak when deleting client from client list

Signed-off-by: Rob White <rob@blue-wave.net>

Diff: diff --git a/src/client_list.c b/src/client_list.c
index 23a20d11..1d46b438 100644
--- a/src/client_list.c
+++ b/src/client_list.c
@@ -171,14 +171,18 @@ void client_reset(t_client *client)
 	safe_snprintf(client->token, STATUS_BUF, "%04hx%04hx", rand16(), rand16());
 	hash_str(hash, STATUS_BUF, client->token);
 	client->hid = safe_strdup(hash);
 	free(hash);
 
-	// Reset custom and client_type
+	// Reset custom, client_type and cpi_query
 	client->custom = safe_calloc(MID_BUF);
 	client->client_type = safe_calloc(STATUS_BUF);
 
+	if (!client->cpi_query) {
+		client->cpi_query = safe_calloc(STATUS_BUF);
+	}
+
 	//Reset cid and remove cidfile using rmcid
 	if (client->cid) {
 
 		if (strlen(client->cid) > 0) {
 			msg = safe_calloc(SMALL_BUF);
@@ -186,14 +190,14 @@ void client_reset(t_client *client)
 			safe_snprintf(cidinfo, MID_BUF, "cid=\"%s\"", client->cid);
 			write_client_info(msg, SMALL_BUF, "rmcid", client->cid, cidinfo);
 			free(msg);
 			free(cidinfo);
 		}
-
-		client->cid = safe_calloc(SMALL_BUF);
 	}
 
+	client->cid = safe_calloc(SMALL_BUF);
+
 }
 
 /**
  *  Given an IP address, add a client corresponding to that IP to client list.
  *  Return a pointer to the new client list entry, or to an existing entry
@@ -426,10 +430,20 @@ _client_list_free_node(t_client *client)
 			free(msg);
 			free(cidinfo);
 		}
 	}
 
+	free(client->token);
+	free(client->hid);
+	free(client->custom);
+	free(client->client_type);
+	free(client->cid);
+
+	if (strcmp(client->cpi_query, "") == 0) {
+		free(client->cpi_query);
+	}
+
 	free(client);
 }
 
 /**
  * @brief Deletes a client from the client list
diff --git a/src/http_microhttpd.c b/src/http_microhttpd.c
index d680785c..13a29f42 100644
--- a/src/http_microhttpd.c
+++ b/src/http_microhttpd.c
@@ -1383,12 +1383,10 @@ static int redirect_to_splashpage(struct MHD_Connection *connection, t_client *c
 	uh_urlencode(originurl, CUSTOM_ENC, originurl_raw, strlen(originurl_raw));
 
 	if (strcmp(url, "/login") == 0) {
 		client->cpi_query = safe_strdup(originurl);
 		debug(LOG_DEBUG, "RFC8910 request: %s", client->cpi_query);
-	} else {
-		client->cpi_query = "none";
 	}
 
 	debug(LOG_DEBUG, "originurl_raw: %s", originurl_raw);
 	debug(LOG_DEBUG, "originurl: %s", originurl);
 

Vulnerable code: 	// Reset custom and client_type

		client->cid = safe_calloc(SMALL_BUF);
	} else {
		client->cpi_query = "none";
Fixed code: 	// Reset custom, client_type and cpi_query
	if (!client->cpi_query) {
		client->cpi_query = safe_calloc(STATUS_BUF);
	}

	client->cid = safe_calloc(SMALL_BUF);

	free(client->token);
	free(client->hid);
	free(client->custom);
	free(client->client_type);
	free(client->cid);

	if (strcmp(client->cpi_query, "") == 0) {
		free(client->cpi_query);
	}