Merge branch 'development-v6' into new/validator

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2023-11-28 22:21:53 +01:00
commit 50ddbc9181
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
10 changed files with 99 additions and 91 deletions

View File

@ -311,10 +311,6 @@ components:
netmask:
type: string
x-format: ipv4
domain:
type: string
description: |
*Note:* This setting is deprecated and will be removed in a future release. Use dns.domain instead.
leaseTime:
type: string
ipv6:
@ -645,7 +641,6 @@ components:
start: "192.168.0.10"
end: "192.168.0.250"
router: "192.168.0.1"
domain: "lan"
netmask: "0.0.0.0"
leaseTime: "24h"
ipv6: true

View File

@ -163,7 +163,7 @@ int api_stats_top_domains(struct ftl_conn *api)
// /api/stats/top_domains?blocked=true
if(api->request->query_string != NULL)
{
// Should blocked clients be shown?
// Should blocked domains be shown?
get_bool_var(api->request->query_string, "blocked", &blocked);
// Does the user request a non-default number of replies?
@ -229,7 +229,7 @@ int api_stats_top_domains(struct ftl_conn *api)
// Skip this domain if there is a filter on it (but only if not in audit mode)
if(!audit)
{
// Check if this client should be skipped
// Check if this domain should be skipped
bool skip_domain = false;
for(unsigned int j = 0; j < excludeDomains; j++)
{
@ -293,7 +293,6 @@ int api_stats_top_domains(struct ftl_conn *api)
int api_stats_top_clients(struct ftl_conn *api)
{
int count = 10;
bool includezeroclients = false;
int *temparray = calloc(2*counters->clients, sizeof(int*));
if(temparray == NULL)
{
@ -325,9 +324,6 @@ int api_stats_top_clients(struct ftl_conn *api)
// Does the user request a non-default number of replies?
// Note: We do not accept zero query requests here
get_int_var(api->request->query_string, "count", &count);
// Show also clients which have not been active recently?
get_bool_var(api->request->query_string, "withzero", &includezeroclients);
}
// Lock shared memory
@ -366,18 +362,18 @@ int api_stats_top_clients(struct ftl_conn *api)
continue;
// Skip this client if there is a filter on it
bool skip_domain = false;
bool skip_client = false;
for(unsigned int j = 0; j < excludeClients; j++)
{
cJSON *item = cJSON_GetArrayItem(config.webserver.api.excludeClients.v.json, j);
if(strcmp(getstr(client->ippos), item->valuestring) == 0 ||
strcmp(getstr(client->namepos), item->valuestring) == 0)
{
skip_domain = true;
skip_client = true;
break;
}
}
if(skip_domain)
if(skip_client)
continue;
// Hidden client, probably due to privacy level. Skip this in the top lists
@ -388,10 +384,9 @@ int api_stats_top_clients(struct ftl_conn *api)
const char *client_ip = getstr(client->ippos);
const char *client_name = getstr(client->namepos);
// Return this client if either
// - "withzero" option is set, and/or
// - the client made at least one query within the most recent 24 hours
if(includezeroclients || count > 0)
// Return this client if the client made at least one query
// within the most recent 24 hours
if(client_count > 0)
{
cJSON *client_item = JSON_NEW_OBJECT();
JSON_REF_STR_IN_OBJECT(client_item, "name", client_name);

View File

@ -688,8 +688,8 @@ void initConfig(struct config *conf)
conf->dns.revServer.target.c = validate_ip_port;
conf->dns.revServer.domain.k = "dns.revServer.domain";
conf->dns.revServer.domain.h = "Domain used for the reverse server feature";
conf->dns.revServer.domain.a = cJSON_CreateStringReference("<valid domain>, typically set to the same value as dhcp.domain");
conf->dns.revServer.domain.h = "Domain used for the reverse server feature (e.g., \"fritz.box\")";
conf->dns.revServer.domain.a = cJSON_CreateStringReference("<valid domain>");
conf->dns.revServer.domain.t = CONF_STRING;
conf->dns.revServer.domain.d.s = (char*)"";
conf->dns.revServer.domain.f = FLAG_RESTART_FTL;
@ -723,14 +723,6 @@ void initConfig(struct config *conf)
conf->dhcp.router.f = FLAG_RESTART_FTL;
memset(&conf->dhcp.router.d.in_addr, 0, sizeof(struct in_addr));
conf->dhcp.domain.k = "dhcp.domain";
conf->dhcp.domain.h = "The DNS domain used by your Pi-hole (*** DEPRECATED ***)\n This setting is deprecated and will be removed in a future version. Please use dns.domain instead. Setting it to any non-default value will overwrite the value of dns.domain if it is still set to its default value.";
conf->dhcp.domain.a = cJSON_CreateStringReference("<any valid domain>");
conf->dhcp.domain.t = CONF_STRING;
conf->dhcp.domain.f = FLAG_RESTART_FTL | FLAG_ADVANCED_SETTING;
conf->dhcp.domain.d.s = (char*)"lan";
conf->dhcp.domain.c = validate_domain;
conf->dhcp.netmask.k = "dhcp.netmask";
conf->dhcp.netmask.h = "The netmask used by your Pi-hole. For directly connected networks (i.e., networks on which the machine running Pi-hole has an interface) the netmask is optional and may be set to an empty string (\"\"): it will then be determined from the interface configuration itself. For networks which receive DHCP service via a relay agent, we cannot determine the netmask itself, so it should explicitly be specified, otherwise Pi-hole guesses based on the class (A, B or C) of the network address.";
conf->dhcp.netmask.a = cJSON_CreateStringReference("<any valid netmask> (e.g., \"255.255.255.0\") or empty string (\"\") for auto-discovery");
@ -880,7 +872,7 @@ void initConfig(struct config *conf)
conf->webserver.session.timeout.k = "webserver.session.timeout";
conf->webserver.session.timeout.h = "Session timeout in seconds. If a session is inactive for more than this time, it will be terminated. Sessions are continuously refreshed by the web interface, preventing sessions from timing out while the web interface is open.\n This option may also be used to make logins persistent for long times, e.g. 86400 seconds (24 hours), 604800 seconds (7 days) or 2592000 seconds (30 days). Note that the total number of concurrent sessions is limited so setting this value too high may result in users being rejected and unable to log in if there are already too many sessions active.";
conf->webserver.session.timeout.t = CONF_UINT;
conf->webserver.session.timeout.d.ui = 300u;
conf->webserver.session.timeout.d.ui = 1800u;
conf->webserver.session.restore.k = "webserver.session.restore";
conf->webserver.session.restore.h = "Should Pi-hole backup and restore sessions from the database? This is useful if you want to keep your sessions after a restart of the web interface.";
@ -983,7 +975,7 @@ void initConfig(struct config *conf)
conf->webserver.api.excludeDomains.k = "webserver.api.excludeDomains";
conf->webserver.api.excludeDomains.h = "Array of domains to be excluded from certain API responses\n Example: [ \"google.de\", \"pi-hole.net\" ]";
conf->webserver.api.excludeDomains.a = cJSON_CreateStringReference("array of IP addresses and/or hostnames");
conf->webserver.api.excludeDomains.a = cJSON_CreateStringReference("array of domains");
conf->webserver.api.excludeDomains.t = CONF_JSON_STRING_ARRAY;
conf->webserver.api.excludeDomains.d.json = cJSON_CreateArray();

View File

@ -187,7 +187,6 @@ struct config {
struct conf_item start;
struct conf_item end;
struct conf_item router;
struct conf_item domain;
struct conf_item netmask;
struct conf_item leaseTime;
struct conf_item ipv6;

View File

@ -25,25 +25,6 @@
// defined in config/config.c
extern uint8_t last_checksum[SHA256_DIGEST_SIZE];
static void migrate_config(void)
{
// Migrating dhcp.domain -> dns.domain
if(strcmp(config.dns.domain.v.s, config.dns.domain.d.s) == 0)
{
// If the domain is the same as the default, check if the dhcp domain
// is different from the default. If so, migrate it
if(strcmp(config.dhcp.domain.v.s, config.dhcp.domain.d.s) != 0)
{
// Migrate dhcp.domain -> dns.domain
log_info("Migrating dhcp.domain = \"%s\" -> dns.domain", config.dhcp.domain.v.s);
if(config.dns.domain.t == CONF_STRING_ALLOCATED)
free(config.dns.domain.v.s);
config.dns.domain.v.s = strdup(config.dhcp.domain.v.s);
config.dns.domain.t = CONF_STRING_ALLOCATED;
}
}
}
bool writeFTLtoml(const bool verbose)
{
// Try to open a temporary config file for writing
@ -68,9 +49,6 @@ bool writeFTLtoml(const bool verbose)
fputs(timestring, fp);
fputs("\n\n", fp);
// Perform possible config migration
migrate_config();
// Iterate over configuration and store it into the file
char *last_path = (char*)"";
for(unsigned int i = 0; i < CONFIG_ELEMENTS; i++)

View File

@ -896,8 +896,8 @@ static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
** In either case, ppst references a caller-owned PerStreamTags
** struct which may be filled in if none of the known writable
** streams is being held by consoleInfo. The ppf parameter is an
** output when chix!=0 and an input when chix==0.
** streams is being held by consoleInfo. The ppf parameter is a
** byref output when chix!=0 and a byref input when chix==0.
*/
static PerStreamTags *
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
@ -910,7 +910,7 @@ getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
ppstTry = &consoleInfo.pstSetup[chix];
pfEmit = ppst->pf;
}else pfEmit = ppstTry->pf;
if( !isValidStreamInfo(ppst) ){
if( !isValidStreamInfo(ppstTry) ){
pfEmit = (chix > 1)? stderr : stdout;
ppstTry = ppst;
streamOfConsole(pfEmit, ppstTry);

View File

@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.44.1. By combining all the individual C code files into this
** version 3.44.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@ -18,7 +18,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** d295f48e8f367b066b881780c98bdf980a1d.
** ebead0e7230cd33bcec9f95d2183069565b9.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@ -459,9 +459,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.44.1"
#define SQLITE_VERSION_NUMBER 3044001
#define SQLITE_SOURCE_ID "2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4"
#define SQLITE_VERSION "3.44.2"
#define SQLITE_VERSION_NUMBER 3044002
#define SQLITE_SOURCE_ID "2023-11-24 11:41:44 ebead0e7230cd33bcec9f95d2183069565b9e709bf745c9b5db65cc0cbf92c0f"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -84183,10 +84183,11 @@ static int growOpArray(Vdbe *v, int nOp){
** sqlite3CantopenError(lineno)
*/
static void test_addop_breakpoint(int pc, Op *pOp){
static int n = 0;
static u64 n = 0;
(void)pc;
(void)pOp;
n++;
if( n==LARGEST_UINT64 ) abort(); /* so that n is used, preventing a warning */
}
#endif
@ -92330,11 +92331,12 @@ SQLITE_API int sqlite3_found_count = 0;
** sqlite3CantopenError(lineno)
*/
static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
static int n = 0;
static u64 n = 0;
(void)pc;
(void)pOp;
(void)v;
n++;
if( n==LARGEST_UINT64 ) abort(); /* So that n is used, preventing a warning */
}
#endif
@ -143612,7 +143614,8 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(
NameContext sNC;
assert( pSelect!=0 );
assert( (pSelect->selFlags & SF_Resolved)!=0 );
testcase( (pSelect->selFlags & SF_Resolved)==0 );
assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT );
assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 );
assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB );
if( db->mallocFailed || IN_RENAME_OBJECT ) return;
@ -241504,18 +241507,24 @@ static void fts5DoSecureDelete(
iOff = iStart;
/* Set variable bLastInDoclist to true if this entry happens to be
** the last rowid in the doclist for its term. */
/* If the position-list for the entry being removed flows over past
** the end of this page, delete the portion of the position-list on the
** next page and beyond.
**
** Set variable bLastInDoclist to true if this entry happens
** to be the last rowid in the doclist for its term. */
if( iNextOff>=iPgIdx ){
int pgno = pSeg->iLeafPgno+1;
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
iNextOff = iPgIdx;
}
if( pSeg->bDel==0 ){
if( iNextOff>=iPgIdx ){
int pgno = pSeg->iLeafPgno+1;
fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
iNextOff = iPgIdx;
}else{
if( iNextOff!=iPgIdx ){
/* Loop through the page-footer. If iNextOff (offset of the
** entry following the one we are removing) is equal to the
** offset of a key on this page, then the entry is the last
** in its doclist. */
** in its doclist. */
int iKeyOff = 0;
for(iIdx=0; iIdx<nIdx; /* no-op */){
u32 iVal = 0;
@ -247610,7 +247619,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4", -1, SQLITE_TRANSIENT);
sqlite3_result_text(pCtx, "fts5: 2023-11-24 11:41:44 ebead0e7230cd33bcec9f95d2183069565b9e709bf745c9b5db65cc0cbf92c0f", -1, SQLITE_TRANSIENT);
}
/*

View File

@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.44.1"
#define SQLITE_VERSION_NUMBER 3044001
#define SQLITE_SOURCE_ID "2023-11-22 14:18:12 d295f48e8f367b066b881780c98bdf980a1d550397d5ba0b0e49842c95b3e8b4"
#define SQLITE_VERSION "3.44.2"
#define SQLITE_VERSION_NUMBER 3044002
#define SQLITE_SOURCE_ID "2023-11-24 11:41:44 ebead0e7230cd33bcec9f95d2183069565b9e709bf745c9b5db65cc0cbf92c0f"
/*
** CAPI3REF: Run-Time Library Version Numbers

View File

@ -294,6 +294,26 @@ bool generate_certificate(const char* certfile, bool rsa, const char *domain)
return true;
}
static bool check_wildcard_domain(const char *domain, char *san, const size_t san_len)
{
// Also check if the SAN is a wildcard domain and if the domain
// matches the wildcard (e.g. "*.pi-hole.net" and "abc.pi-hole.net")
const bool is_wild = san_len > 1 && san[0] == '*';
if(!is_wild)
return false;
// The domain must be at least as long as the wildcard domain
const size_t domain_len = strlen(domain);
if(domain_len < san_len - 1)
return false;
// Check if the domain ends with the wildcard domain
// Attention: The SAN is not NUL-terminated, so we need to
// use the length field
const char *wild_domain = domain + domain_len - san_len + 1;
return strncasecmp(wild_domain, san + 1, san_len) == 0;
}
// This function reads a X.509 certificate from a file and prints a
// human-readable representation of the certificate to stdout. If a domain is
// specified, we only check if this domain is present in the certificate.
@ -358,26 +378,55 @@ enum cert_check read_certificate(const char* certfile, const char *domain, const
goto next_san;
// Check if the SAN matches the domain
// Attention: The SAN is not NUL-terminated, so we need to
// use the length field
if(strncasecmp(domain, (char*)san.san.unstructured_name.p, san.san.unstructured_name.len) == 0)
{
found = true;
// Free resources
mbedtls_x509_free_subject_alt_name(&san);
break;
}
// Also check if the SAN is a wildcard domain and if the domain
// matches the wildcard
if(check_wildcard_domain(domain, (char*)san.san.unstructured_name.p, san.san.unstructured_name.len))
{
found = true;
// Free resources
mbedtls_x509_free_subject_alt_name(&san);
break;
}
next_san:
// Free resources
mbedtls_x509_free_subject_alt_name(&san);
// Go to next SAN
sans = sans->next;
}
// Also check against the common name (CN) field
char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE];
if(mbedtls_x509_dn_gets(subject, sizeof(subject), &crt.subject) > 0)
const size_t subject_len = mbedtls_x509_dn_gets(subject, sizeof(subject), &crt.subject);
if(subject_len > 0)
{
// Check subject == "CN=<domain>"
if(strlen(subject) > 3 && strncasecmp(subject, "CN=", 3) == 0 && strcasecmp(domain, subject + 3) == 0)
found = true;
// Check subjects prefixed with "CN="
if(subject_len > 3 && strncasecmp(subject, "CN=", 3) == 0)
{
// Check subject + 3 to skip the prefix
if(strncasecmp(domain, subject + 3, subject_len - 3) == 0)
found = true;
// Also check if the subject is a wildcard domain
else if(check_wildcard_domain(domain, subject + 3, subject_len - 3))
found = true;
}
// Check subject == "<domain>"
else if(strcasecmp(domain, subject) == 0)
found = true;
// Also check if the subject is a wildcard domain and if the domain
// matches the wildcard
else if(check_wildcard_domain(domain, subject, subject_len))
found = true;
}

View File

@ -370,7 +370,7 @@
# Domain used for the reverse server feature
#
# Possible values are:
# <valid domain>, typically set to the same value as dhcp.domain
# <valid domain> (e.g., "fritz.box")
domain = ""
[dhcp]
@ -396,15 +396,6 @@
# <ip-addr>, e.g., "192.168.0.1"
router = ""
# The DNS domain used by your Pi-hole (*** DEPRECATED ***)
# This setting is deprecated and will be removed in a future version. Please use
# dns.domain instead. Setting it to any non-default value will overwrite the value of
# dns.domain if it is still set to its default value.
#
# Possible values are:
# <any valid domain>
domain = "lan"
# The netmask used by your Pi-hole. For directly connected networks (i.e., networks on
# which the machine running Pi-hole has an interface) the netmask is optional and may
# be set to "0.0.0.0": it will then be determined from the interface configuration
@ -694,7 +685,7 @@
# Example: [ "google.de", "pi-hole.net" ]
#
# Possible values are:
# array of IP addresses and/or hostnames
# array of domains
excludeDomains = []
# How much history should be imported from the database [seconds]? (max 24*60*60 =