mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Merge branch 'development-v6' into tweak/domain_array
This commit is contained in:
@@ -7,5 +7,6 @@ patch -p1 < patch/civetweb/0001-Always-Kepler-syntax-for-Lua-server-pages.patch
|
||||
patch -p1 < patch/civetweb/0001-Add-FTL-URI-rewriting-changes-to-CivetWeb.patch
|
||||
patch -p1 < patch/civetweb/0001-Add-mbedTLS-debug-logging-hook.patch
|
||||
patch -p1 < patch/civetweb/0001-Register-CSRF-token-in-conn-request_info.patch
|
||||
patch -p1 < patch/civetweb/0001-Do-not-try-to-guess-server-hostname-in-Civetweb-when.patch
|
||||
|
||||
echo "ALL PATCHES APPLIED OKAY"
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From e41d902b5b01896360e1235aebabd3eb352158aa Mon Sep 17 00:00:00 2001
|
||||
From: DL6ER <dl6er@dl6er.de>
|
||||
Date: Sun, 8 Oct 2023 14:31:20 +0200
|
||||
Subject: [PATCH] Do not try to guess server hostname in Civetweb when
|
||||
redirecting directory URIs to end with a slash
|
||||
|
||||
Signed-off-by: DL6ER <dl6er@dl6er.de>
|
||||
---
|
||||
src/webserver/civetweb/civetweb.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/webserver/civetweb/civetweb.c b/src/webserver/civetweb/civetweb.c
|
||||
index f44b17ba..3df8eab9 100644
|
||||
--- a/src/webserver/civetweb/civetweb.c
|
||||
+++ b/src/webserver/civetweb/civetweb.c
|
||||
@@ -15306,7 +15306,9 @@ handle_request(struct mg_connection *conn)
|
||||
if (!new_path) {
|
||||
mg_send_http_error(conn, 500, "out or memory");
|
||||
} else {
|
||||
- mg_get_request_link(conn, new_path, buflen - 1);
|
||||
+ /* Pi-hole modification */
|
||||
+ //mg_get_request_link(conn, new_path, buflen - 1);
|
||||
+ strcpy(new_path, ri->local_uri_raw);
|
||||
strcat(new_path, "/");
|
||||
if (ri->query_string) {
|
||||
/* Append ? and query string */
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -44,6 +44,7 @@ static struct {
|
||||
{ "/api/groups", "/{name}", api_list, { false, true, 0 }, true, HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_DELETE },
|
||||
{ "/api/lists", "/{list}", api_list, { false, true, 0 }, true, HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_DELETE },
|
||||
{ "/api/info/client", "", api_info_client, { false, true, 0 }, false, HTTP_GET },
|
||||
{ "/api/info/login", "", api_info_login, { false, true, 0 }, false, HTTP_GET },
|
||||
{ "/api/info/system", "", api_info_system, { false, true, 0 }, true, HTTP_GET },
|
||||
{ "/api/info/database", "", api_info_database, { false, true, 0 }, true, HTTP_GET },
|
||||
{ "/api/info/sensors", "", api_info_sensors, { false, true, 0 }, true, HTTP_GET },
|
||||
|
||||
@@ -60,6 +60,7 @@ int api_info_version(struct ftl_conn *api);
|
||||
int api_info_messages_count(struct ftl_conn *api);
|
||||
int api_info_messages(struct ftl_conn *api);
|
||||
int api_info_metrics(struct ftl_conn *api);
|
||||
int api_info_login(struct ftl_conn *api);
|
||||
|
||||
// Config methods
|
||||
int api_config(struct ftl_conn *api);
|
||||
|
||||
@@ -302,7 +302,6 @@ static int get_all_sessions(struct ftl_conn *api, cJSON *json)
|
||||
static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_id, const time_t now)
|
||||
{
|
||||
cJSON *session = JSON_NEW_OBJECT();
|
||||
const bool dns = get_blockingstatus() != DNS_FAILED;
|
||||
|
||||
// Authentication not needed
|
||||
if(user_id == API_AUTH_LOCALHOST || user_id == API_AUTH_EMPTYPASS)
|
||||
@@ -312,7 +311,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
||||
JSON_ADD_NULL_TO_OBJECT(session, "sid");
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", -1);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -325,7 +323,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
||||
JSON_REF_STR_IN_OBJECT(session, "csrf", auth_data[user_id].csrf);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", auth_data[user_id].valid_until - now);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,7 +332,6 @@ static int get_session_object(struct ftl_conn *api, cJSON *json, const int user_
|
||||
JSON_ADD_NULL_TO_OBJECT(session, "sid");
|
||||
JSON_ADD_NUMBER_TO_OBJECT(session, "validity", -1);
|
||||
JSON_ADD_ITEM_TO_OBJECT(json, "session", session);
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ components:
|
||||
$ref: 'auth.yaml#/components/examples/no_login_required'
|
||||
login_required:
|
||||
$ref: 'auth.yaml#/components/examples/login_required'
|
||||
dns_failure:
|
||||
$ref: 'auth.yaml#/components/examples/dns_failure'
|
||||
post:
|
||||
summary: Submit password for login
|
||||
tags:
|
||||
@@ -157,6 +155,7 @@ components:
|
||||
tags:
|
||||
- Authentication
|
||||
operationId: "get_auth_totp"
|
||||
security: []
|
||||
description: Suggest new TOTP credentials for two-factor authentication (2FA)
|
||||
responses:
|
||||
'200':
|
||||
@@ -245,9 +244,6 @@ components:
|
||||
validity:
|
||||
type: integer
|
||||
description: Remaining lifetime of this session unless refreshed (seconds)
|
||||
dns:
|
||||
type: boolean
|
||||
description: Whether the DNS server is up and running. False only in failed state
|
||||
|
||||
password:
|
||||
type: object
|
||||
@@ -371,7 +367,6 @@ components:
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: 300
|
||||
dns: true
|
||||
no_login_required:
|
||||
summary: No login required for this client
|
||||
value:
|
||||
@@ -381,7 +376,6 @@ components:
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
login_required:
|
||||
summary: Login required
|
||||
value:
|
||||
@@ -391,7 +385,6 @@ components:
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
login_failed:
|
||||
summary: Login failed
|
||||
value:
|
||||
@@ -401,17 +394,6 @@ components:
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: true
|
||||
dns_failure:
|
||||
summary: DNS server failure
|
||||
value:
|
||||
session:
|
||||
valid: false
|
||||
totp: false
|
||||
sid: null
|
||||
csrf: null
|
||||
validity: -1
|
||||
dns: false
|
||||
errors:
|
||||
no_payload:
|
||||
summary: Bad request (no valid JSON payload)
|
||||
|
||||
@@ -6,6 +6,7 @@ components:
|
||||
summary: Get information about requesting client
|
||||
tags:
|
||||
- "FTL information"
|
||||
security: []
|
||||
operationId: "get_client"
|
||||
description: |
|
||||
The property `timer` may contain additional details concerning a temporary en-/disabling.
|
||||
@@ -278,6 +279,24 @@ components:
|
||||
allOf:
|
||||
- $ref: 'common.yaml#/components/errors/unauthorized'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
login:
|
||||
get:
|
||||
summary: Login page related information
|
||||
tags:
|
||||
- "FTL information"
|
||||
operationId: "get_logininfo"
|
||||
security: []
|
||||
description: |
|
||||
This API hook returns information used on the login page to possibly display messages/warnings.
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: 'info.yaml#/components/schemas/login'
|
||||
- $ref: 'common.yaml#/components/schemas/took'
|
||||
|
||||
schemas:
|
||||
client:
|
||||
@@ -1068,6 +1087,15 @@ components:
|
||||
type: integer
|
||||
description: Number of items
|
||||
example: 42
|
||||
login:
|
||||
type: object
|
||||
properties:
|
||||
https_port:
|
||||
type: integer
|
||||
description: HTTPS port of the Pi-hole webserver (0 if disabled)
|
||||
dns:
|
||||
type: boolean
|
||||
description: Whether the DNS server is up and running. False only in failed state
|
||||
examples:
|
||||
errors:
|
||||
messages:
|
||||
|
||||
@@ -190,6 +190,9 @@ paths:
|
||||
/info/metrics:
|
||||
$ref: 'info.yaml#/components/paths/metrics'
|
||||
|
||||
/info/login:
|
||||
$ref: 'info.yaml#/components/paths/login'
|
||||
|
||||
/logs/dnsmasq:
|
||||
$ref: 'logs.yaml#/components/paths/logs/dnsmasq'
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ int api_docs(struct ftl_conn *api)
|
||||
// Handle resource request by redirecting to "/"
|
||||
if(strcmp(api->request->request_uri, "/api/docs") == 0)
|
||||
{
|
||||
log_debug(DEBUG_API, "Redirecting /api/docs --301--> /api/docs/");
|
||||
mg_send_http_redirect(api->conn, "/api/docs/", 301);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
#include <limits.h>
|
||||
#include "metrics.h"
|
||||
|
||||
// get_https_port()
|
||||
#include "webserver/webserver.h"
|
||||
|
||||
// DIR
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -1032,3 +1035,15 @@ int api_info_metrics(struct ftl_conn *api)
|
||||
JSON_ADD_ITEM_TO_OBJECT(json2, "metrics", json);
|
||||
JSON_SEND_OBJECT(json2);
|
||||
}
|
||||
|
||||
int api_info_login(struct ftl_conn *api)
|
||||
{
|
||||
cJSON *json = JSON_NEW_OBJECT();
|
||||
|
||||
const bool dns = get_blockingstatus() != DNS_FAILED;
|
||||
JSON_ADD_BOOL_TO_OBJECT(json, "dns", dns);
|
||||
|
||||
JSON_ADD_NUMBER_TO_OBJECT(json, "https_port", get_https_port());
|
||||
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
+8
-6
@@ -311,18 +311,20 @@ void parse_args(int argc, char* argv[])
|
||||
|
||||
if(argc > 1 && strcmp(argv[1], "--gen-x509") == 0)
|
||||
{
|
||||
if(argc != 3 && argc != 4)
|
||||
if(argc < 3 || argc > 5)
|
||||
{
|
||||
printf("Usage: %s --gen-x509 <output file> [rsa]\n", argv[0]);
|
||||
printf("Example: %s --gen-x509 /etc/pihole/tls.pem\n", argv[0]);
|
||||
printf(" or: %s --gen-x509 /etc/pihole/tls.pem rsa\n", argv[0]);
|
||||
printf("Usage: %s --gen-x509 <output file> [<domain>] [rsa]\n", argv[0]);
|
||||
printf("Example: %s --gen-x509 /etc/pihole/tls.pem\n", argv[0]);
|
||||
printf(" with domain: %s --gen-x509 /etc/pihole/tls.pem pi.hole\n", argv[0]);
|
||||
printf(" RSA with domain: %s --gen-x509 /etc/pihole/tls.pem nanopi.lan rsa\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Enable stdout printing
|
||||
cli_mode = true;
|
||||
log_ctrl(false, true);
|
||||
const bool rsa = argc == 4 && strcasecmp(argv[3], "rsa") == 0;
|
||||
exit(generate_certificate(argv[2], rsa) ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
const char *domain = argc > 3 ? argv[3] : "pi.hole";
|
||||
const bool rsa = argc > 4 && strcasecmp(argv[4], "rsa") == 0;
|
||||
exit(generate_certificate(argv[2], rsa, domain) ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// If the first argument is "gravity" (e.g., /usr/bin/pihole-FTL gravity),
|
||||
|
||||
+2
-1
@@ -509,7 +509,8 @@ void initConfig(struct config *conf)
|
||||
{ "LOCAL", "Allow only local requests. This setting accepts DNS queries only from hosts whose address is on a local subnet, i.e., a subnet for which an interface exists on the server. It is intended to be set as a default on installation, to allow unconfigured installations to be useful but also safe from being used for DNS amplification attacks if (accidentally) running public." },
|
||||
{ "SINGLE", "Permit all origins, accept only on the specified interface. Respond only to queries arriving on the specified interface. The loopback (lo) interface is automatically added to the list of interfaces to use when this option is used. Make sure your Pi-hole is properly firewalled!" },
|
||||
{ "BIND", "By default, FTL binds the wildcard address. If this is not what you want, you can use this option as it forces FTL to really bind only the interfaces it is listening on. Note that this may result in issues when the interface may go down (cable unplugged, etc.). About the only time when this is useful is when running another nameserver on the same port on the same machine. This may also happen if you run a virtualization API such as libvirt. When this option is used, IP alias interface labels (e.g. enp2s0:0) are checked rather than interface names." },
|
||||
{ "ALL", "Permit all origins, accept on all interfaces. Make sure your Pi-hole is properly firewalled! This truly allows any traffic to be replied to and is a dangerous thing to do as your Pi-hole could become an open resolver. You should always ask yourself if the first option doesn't work for you as well." }
|
||||
{ "ALL", "Permit all origins, accept on all interfaces. Make sure your Pi-hole is properly firewalled! This truly allows any traffic to be replied to and is a dangerous thing to do as your Pi-hole could become an open resolver. You should always ask yourself if the first option doesn't work for you as well." },
|
||||
{ "NONE", "Do not add any configuration concerning the listening mode to the dnsmasq configuration file. This is useful if you want to manually configure the listening mode in auxiliary configuration files. This option is really meant for advanced users only, support for this option may be limited." }
|
||||
};
|
||||
CONFIG_ADD_ENUM_OPTIONS(conf->dns.listeningMode.a, listeningMode);
|
||||
}
|
||||
|
||||
@@ -360,6 +360,9 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
|
||||
fprintf(pihole_conf, "interface=%s\n", interface);
|
||||
fputs("bind-interfaces\n", pihole_conf);
|
||||
break;
|
||||
case LISTEN_NONE:
|
||||
fputs("# No interface configuration applied, make sure to cover this yourself\n", pihole_conf);
|
||||
break;
|
||||
}
|
||||
fputs("\n", pihole_conf);
|
||||
|
||||
|
||||
@@ -2207,9 +2207,14 @@ bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *
|
||||
|
||||
// Convert to string
|
||||
if(listtype == GRAVITY_DOMAINLIST_ALLOW_EXACT ||
|
||||
listtype == GRAVITY_DOMAINLIST_DENY_EXACT ||
|
||||
listtype == GRAVITY_DOMAINLIST_ALLOW_REGEX ||
|
||||
listtype == GRAVITY_DOMAINLIST_DENY_REGEX)
|
||||
listtype == GRAVITY_DOMAINLIST_ALLOW_ALL ||
|
||||
listtype == GRAVITY_DOMAINLIST_DENY_EXACT ||
|
||||
listtype == GRAVITY_DOMAINLIST_DENY_REGEX ||
|
||||
listtype == GRAVITY_DOMAINLIST_DENY_ALL ||
|
||||
listtype == GRAVITY_DOMAINLIST_ALL_EXACT ||
|
||||
listtype == GRAVITY_DOMAINLIST_ALL_REGEX ||
|
||||
listtype == GRAVITY_DOMAINLIST_ALL_ALL)
|
||||
{
|
||||
switch(row->type_int)
|
||||
{
|
||||
|
||||
@@ -1262,7 +1262,7 @@ static void shellDtostr(
|
||||
char z[400];
|
||||
if( n<1 ) n = 1;
|
||||
if( n>350 ) n = 350;
|
||||
sprintf(z, "%#+.*e", n, r);
|
||||
snprintf(z, sizeof(z)-1, "%#+.*e", n, r);
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
|
||||
+26
-19
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.43.1. By combining all the individual C code files into this
|
||||
** version 3.43.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
|
||||
** d3a40c05c49e1a49264912b1a05bc2143ac.
|
||||
** 310099cce5a487035fa535dd3002c59ac7f.
|
||||
*/
|
||||
#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.43.1"
|
||||
#define SQLITE_VERSION_NUMBER 3043001
|
||||
#define SQLITE_SOURCE_ID "2023-09-11 12:01:27 2d3a40c05c49e1a49264912b1a05bc2143ac0e7c3df588276ce80a4cbc9bd1b0"
|
||||
#define SQLITE_VERSION "3.43.2"
|
||||
#define SQLITE_VERSION_NUMBER 3043002
|
||||
#define SQLITE_SOURCE_ID "2023-10-10 12:14:04 4310099cce5a487035fa535dd3002c59ac7f1d1bec68d7cf317fd3e769484790"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -35185,29 +35185,29 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
|
||||
double rr[2];
|
||||
rr[0] = r;
|
||||
rr[1] = 0.0;
|
||||
if( rr[0]>1.84e+19 ){
|
||||
while( rr[0]>1.84e+119 ){
|
||||
if( rr[0]>9.223372036854774784e+18 ){
|
||||
while( rr[0]>9.223372036854774784e+118 ){
|
||||
exp += 100;
|
||||
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
||||
}
|
||||
while( rr[0]>1.84e+29 ){
|
||||
while( rr[0]>9.223372036854774784e+28 ){
|
||||
exp += 10;
|
||||
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
||||
}
|
||||
while( rr[0]>1.84e+19 ){
|
||||
while( rr[0]>9.223372036854774784e+18 ){
|
||||
exp += 1;
|
||||
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
||||
}
|
||||
}else{
|
||||
while( rr[0]<1.84e-82 ){
|
||||
while( rr[0]<9.223372036854774784e-83 ){
|
||||
exp -= 100;
|
||||
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
||||
}
|
||||
while( rr[0]<1.84e+08 ){
|
||||
while( rr[0]<9.223372036854774784e+07 ){
|
||||
exp -= 10;
|
||||
dekkerMul2(rr, 1.0e+10, 0.0);
|
||||
}
|
||||
while( rr[0]<1.84e+18 ){
|
||||
while( rr[0]<9.22337203685477478e+17 ){
|
||||
exp -= 1;
|
||||
dekkerMul2(rr, 1.0e+01, 0.0);
|
||||
}
|
||||
@@ -77024,6 +77024,7 @@ static int rebuildPage(
|
||||
int k; /* Current slot in pCArray->apEnd[] */
|
||||
u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
|
||||
|
||||
assert( nCell>0 );
|
||||
assert( i<iEnd );
|
||||
j = get2byte(&aData[hdr+5]);
|
||||
if( NEVER(j>(u32)usableSize) ){ j = 0; }
|
||||
@@ -77330,6 +77331,7 @@ static int editPage(
|
||||
return SQLITE_OK;
|
||||
editpage_fail:
|
||||
/* Unable to edit this page. Rebuild it from scratch instead. */
|
||||
if( nNew<1 ) return SQLITE_CORRUPT_BKPT;
|
||||
populateCellCache(pCArray, iNew, nNew);
|
||||
return rebuildPage(pCArray, iNew, nNew, pPg);
|
||||
}
|
||||
@@ -100833,8 +100835,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
|
||||
/* Set the value of register r[1] in the SQL statement to integer iRow.
|
||||
** This is done directly as a performance optimization
|
||||
*/
|
||||
v->aMem[1].flags = MEM_Int;
|
||||
v->aMem[1].u.i = iRow;
|
||||
sqlite3VdbeMemSetInt64(&v->aMem[1], iRow);
|
||||
|
||||
/* If the statement has been run before (and is paused at the OP_ResultRow)
|
||||
** then back it up to the point where it does the OP_NotExists. This could
|
||||
@@ -204134,6 +204135,7 @@ static void jsonReplaceFunc(
|
||||
}
|
||||
pParse = jsonParseCached(ctx, argv[0], ctx, argc>1);
|
||||
if( pParse==0 ) return;
|
||||
pParse->nJPRef++;
|
||||
for(i=1; i<(u32)argc; i+=2){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
pParse->useMod = 1;
|
||||
@@ -204146,6 +204148,7 @@ static void jsonReplaceFunc(
|
||||
jsonReturnJson(pParse, pParse->aNode, ctx, 1);
|
||||
replace_err:
|
||||
jsonDebugPrintParse(pParse);
|
||||
jsonParseFree(pParse);
|
||||
}
|
||||
|
||||
|
||||
@@ -204180,6 +204183,7 @@ static void jsonSetFunc(
|
||||
}
|
||||
pParse = jsonParseCached(ctx, argv[0], ctx, argc>1);
|
||||
if( pParse==0 ) return;
|
||||
pParse->nJPRef++;
|
||||
for(i=1; i<(u32)argc; i+=2){
|
||||
zPath = (const char*)sqlite3_value_text(argv[i]);
|
||||
bApnd = 0;
|
||||
@@ -204196,9 +204200,8 @@ static void jsonSetFunc(
|
||||
}
|
||||
jsonDebugPrintParse(pParse);
|
||||
jsonReturnJson(pParse, pParse->aNode, ctx, 1);
|
||||
|
||||
jsonSetDone:
|
||||
/* no cleanup required */;
|
||||
jsonParseFree(pParse);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -239687,7 +239690,6 @@ static void fts5DoSecureDelete(
|
||||
int iIdx = 0;
|
||||
int iStart = 0;
|
||||
int iKeyOff = 0;
|
||||
int iPrevKeyOff = 0;
|
||||
int iDelKeyOff = 0; /* Offset of deleted key, if any */
|
||||
|
||||
nIdx = nPg-iPgIdx;
|
||||
@@ -244249,6 +244251,9 @@ static int fts5FilterMethod(
|
||||
pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
|
||||
}
|
||||
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
if( rc!=SQLITE_OK ) goto filter_out;
|
||||
|
||||
if( pTab->pSortCsr ){
|
||||
/* If pSortCsr is non-NULL, then this call is being made as part of
|
||||
** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
|
||||
@@ -244271,7 +244276,9 @@ static int fts5FilterMethod(
|
||||
pCsr->pExpr = pTab->pSortCsr->pExpr;
|
||||
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
||||
}else if( pCsr->pExpr ){
|
||||
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bOrderByRank ){
|
||||
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||
@@ -245752,7 +245759,7 @@ static void fts5SourceIdFunc(
|
||||
){
|
||||
assert( nArg==0 );
|
||||
UNUSED_PARAM2(nArg, apUnused);
|
||||
sqlite3_result_text(pCtx, "fts5: 2023-09-11 12:01:27 2d3a40c05c49e1a49264912b1a05bc2143ac0e7c3df588276ce80a4cbc9bd1b0", -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(pCtx, "fts5: 2023-10-10 12:14:04 4310099cce5a487035fa535dd3002c59ac7f1d1bec68d7cf317fd3e769484790", -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -146,9 +146,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.43.1"
|
||||
#define SQLITE_VERSION_NUMBER 3043001
|
||||
#define SQLITE_SOURCE_ID "2023-09-11 12:01:27 2d3a40c05c49e1a49264912b1a05bc2143ac0e7c3df588276ce80a4cbc9bd1b0"
|
||||
#define SQLITE_VERSION "3.43.2"
|
||||
#define SQLITE_VERSION_NUMBER 3043002
|
||||
#define SQLITE_SOURCE_ID "2023-10-10 12:14:04 4310099cce5a487035fa535dd3002c59ac7f1d1bec68d7cf317fd3e769484790"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
||||
@@ -1051,6 +1051,8 @@ const char * __attribute__ ((const)) get_listeningMode_str(const enum listening_
|
||||
return "SINGLE";
|
||||
case LISTEN_BIND:
|
||||
return "BIND";
|
||||
case LISTEN_NONE:
|
||||
return "NONE";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1065,6 +1067,8 @@ int __attribute__ ((pure)) get_listeningMode_val(const char *listeningMode)
|
||||
return LISTEN_SINGLE;
|
||||
else if(strcasecmp(listeningMode, "BIND") == 0)
|
||||
return LISTEN_BIND;
|
||||
else if(strcasecmp(listeningMode, "NONE") == 0)
|
||||
return LISTEN_NONE;
|
||||
|
||||
// Invalid value
|
||||
return -1;
|
||||
|
||||
+2
-1
@@ -288,7 +288,8 @@ enum listening_mode {
|
||||
LISTEN_LOCAL,
|
||||
LISTEN_ALL,
|
||||
LISTEN_SINGLE,
|
||||
LISTEN_BIND
|
||||
LISTEN_BIND,
|
||||
LISTEN_NONE
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum fifo_logs {
|
||||
|
||||
@@ -15306,7 +15306,9 @@ handle_request(struct mg_connection *conn)
|
||||
if (!new_path) {
|
||||
mg_send_http_error(conn, 500, "out or memory");
|
||||
} else {
|
||||
mg_get_request_link(conn, new_path, buflen - 1);
|
||||
/* Pi-hole modification */
|
||||
//mg_get_request_link(conn, new_path, buflen - 1);
|
||||
strcpy(new_path, ri->local_uri_raw);
|
||||
strcat(new_path, "/");
|
||||
if (ri->query_string) {
|
||||
/* Append ? and query string */
|
||||
|
||||
+78
-49
@@ -86,6 +86,8 @@ static int redirect_root_handler(struct mg_connection *conn, void *input)
|
||||
// 308 Permanent Redirect from http://pi.hole -> http://pi.hole/admin
|
||||
if(strcmp(uri, "/") == 0)
|
||||
{
|
||||
log_debug(DEBUG_API, "Redirecting / --308--> %s",
|
||||
config.webserver.paths.webhome.v.s);
|
||||
mg_send_http_redirect(conn, config.webserver.paths.webhome.v.s, 308);
|
||||
return 1;
|
||||
}
|
||||
@@ -100,52 +102,23 @@ static int redirect_lp_handler(struct mg_connection *conn, void *input)
|
||||
// Get requested URI
|
||||
const struct mg_request_info *request = mg_get_request_info(conn);
|
||||
const char *uri = request->local_uri_raw;
|
||||
const size_t uri_len = strlen(uri);
|
||||
const char *query_string = request->query_string;
|
||||
const size_t query_len = query_string != NULL ? strlen(query_string) : 0;
|
||||
|
||||
// Remove the ".lp" from the URI
|
||||
char *pos = strstr(uri, ".lp");
|
||||
char *new_uri = calloc(strlen(uri) + query_len, sizeof(char));
|
||||
// Copy everything from before the ".lp" to the new URI
|
||||
strncpy(new_uri, uri, pos - uri);
|
||||
// We allocate uri_len + query_len - 1 bytes, which is enough for the
|
||||
// new URI. The calculation is as follows:
|
||||
// 1. We are saving three bytes by skipping ".lp" at the end of the URI
|
||||
// 2. We are adding one byte for the trailing '\0'
|
||||
// 3. We are adding query_len bytes for the query string (if present)
|
||||
// 4. We are adding one byte for the '?' between URI and query string
|
||||
// (if present)
|
||||
// Total bytes required: uri_len - 3 + query_len + 1 + 1
|
||||
char *new_uri = calloc(uri_len + query_len - 1, sizeof(char));
|
||||
|
||||
// Append query string to the new URI if present
|
||||
if(query_len > 0)
|
||||
{
|
||||
strcat(new_uri, "?");
|
||||
strcat(new_uri, query_string);
|
||||
}
|
||||
|
||||
// Send a 301 redirect to the new URI
|
||||
log_debug(DEBUG_API, "Redirecting %s?%s ==301==> %s",
|
||||
uri, query_string, new_uri);
|
||||
mg_send_http_redirect(conn, new_uri, 301);
|
||||
free(new_uri);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int redirect_slash_handler(struct mg_connection *conn, void *input)
|
||||
{
|
||||
// Get requested URI
|
||||
const struct mg_request_info *request = mg_get_request_info(conn);
|
||||
const char *uri = request->local_uri_raw;
|
||||
const char *query_string = request->query_string;
|
||||
const size_t query_len = query_string != NULL ? strlen(query_string) : 0;
|
||||
|
||||
// Do not redirect if the new URI is the webhome
|
||||
if(strcmp(uri, config.webserver.paths.webhome.v.s) == 0)
|
||||
{
|
||||
log_debug(DEBUG_API, "Not redirecting %s?%s",
|
||||
uri, query_string);
|
||||
|
||||
// Handle as a normal request
|
||||
return request_handler(conn, input);
|
||||
}
|
||||
|
||||
// Remove the trailing slash from the URI
|
||||
char *new_uri = strdup(uri);
|
||||
new_uri[strlen(new_uri) - 1] = '\0';
|
||||
// Copy everything from before the ".lp" to the new URI to effectively
|
||||
// remove it
|
||||
strncpy(new_uri, uri, uri_len - 3);
|
||||
|
||||
// Append query string to the new URI if present
|
||||
if(query_len > 0)
|
||||
@@ -204,6 +177,52 @@ void FTL_mbed_debug(void *user_param, int level, const char *file, int line, con
|
||||
log_web("mbedTLS(%s:%d, %d): %.*s", file, line, level, (int)len, message);
|
||||
}
|
||||
|
||||
#define MAXPORTS 8
|
||||
static struct serverports
|
||||
{
|
||||
bool is_secure;
|
||||
unsigned char protocol; // 1 = IPv4, 2 = IPv4+IPv6, 3 = IPv6
|
||||
in_port_t port;
|
||||
} server_ports[MAXPORTS] = { 0 };
|
||||
static in_port_t https_port = 0;
|
||||
static void get_server_ports(void)
|
||||
{
|
||||
if(ctx == NULL)
|
||||
return;
|
||||
|
||||
// Loop over all listening ports
|
||||
struct mg_server_port mgports[MAXPORTS] = { 0 };
|
||||
if(mg_get_server_ports(ctx, MAXPORTS, mgports) > 0)
|
||||
{
|
||||
// Loop over all ports
|
||||
for(unsigned int i = 0; i < MAXPORTS; i++)
|
||||
{
|
||||
// Stop if no more ports are configured
|
||||
if(mgports[i].protocol == 0)
|
||||
break;
|
||||
|
||||
// Store port information
|
||||
server_ports[i].port = mgports[i].port;
|
||||
server_ports[i].is_secure = mgports[i].is_ssl;
|
||||
server_ports[i].protocol = mgports[i].protocol;
|
||||
|
||||
// Store HTTPS port if not already set
|
||||
if(mgports[i].is_ssl && https_port == 0)
|
||||
https_port = mgports[i].port;
|
||||
|
||||
// Print port information
|
||||
log_debug(DEBUG_API, "Listening on port %d (HTTP%s, IPv%s)",
|
||||
mgports[i].port, mgports[i].is_ssl ? "S" : "",
|
||||
mgports[i].protocol == 1 ? "4" : (mgports[i].protocol == 3 ? "6" : "4+6"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in_port_t __attribute__((pure)) get_https_port(void)
|
||||
{
|
||||
return https_port;
|
||||
}
|
||||
|
||||
void http_init(void)
|
||||
{
|
||||
log_web("Initializing HTTP server on port %s", config.webserver.port.v.s);
|
||||
@@ -277,17 +296,27 @@ void http_init(void)
|
||||
strlen(config.webserver.tls.cert.v.s) > 0)
|
||||
{
|
||||
// Try to generate certificate if not present
|
||||
if(!file_readable(config.webserver.tls.cert.v.s) &&
|
||||
!generate_certificate(config.webserver.tls.cert.v.s, false))
|
||||
if(!file_readable(config.webserver.tls.cert.v.s))
|
||||
{
|
||||
log_err("Generation of SSL/TLS certificate %s failed!",
|
||||
config.webserver.tls.cert.v.s);
|
||||
if(generate_certificate(config.webserver.tls.cert.v.s, false, config.webserver.domain.v.s))
|
||||
{
|
||||
log_info("Created SSL/TLS certificate for %s at %s",
|
||||
config.webserver.domain.v.s, config.webserver.tls.cert.v.s);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_err("Generation of SSL/TLS certificate %s failed!",
|
||||
config.webserver.tls.cert.v.s);
|
||||
}
|
||||
}
|
||||
|
||||
if(file_readable(config.webserver.tls.cert.v.s))
|
||||
{
|
||||
options[++next_option] = "ssl_certificate";
|
||||
options[++next_option] = config.webserver.tls.cert.v.s;
|
||||
|
||||
log_info("Using SSL/TLS certificate file %s",
|
||||
config.webserver.tls.cert.v.s);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -330,14 +359,14 @@ void http_init(void)
|
||||
// Register **.lp -> ** redirect handler
|
||||
mg_set_request_handler(ctx, "**.lp$", redirect_lp_handler, NULL);
|
||||
|
||||
// Register **/ -> ** redirect handler
|
||||
mg_set_request_handler(ctx, "**/$", redirect_slash_handler, NULL);
|
||||
|
||||
// Register handler for the rest
|
||||
mg_set_request_handler(ctx, "**", request_handler, NULL);
|
||||
|
||||
// Prepare prerequisites for Lua
|
||||
allocate_lua();
|
||||
|
||||
// Get server ports
|
||||
get_server_ports();
|
||||
}
|
||||
|
||||
static char *append_to_path(char *path, const char *append)
|
||||
|
||||
@@ -13,4 +13,6 @@
|
||||
void http_init(void);
|
||||
void http_terminate(void);
|
||||
|
||||
in_port_t get_https_port(void) __attribute__((pure));
|
||||
|
||||
#endif // WEBSERVER_H
|
||||
+10
-2
@@ -78,7 +78,7 @@ static int generate_private_key_ec(mbedtls_pk_context *key,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool generate_certificate(const char* certfile, bool rsa)
|
||||
bool generate_certificate(const char* certfile, bool rsa, const char *domain)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_x509write_cert crt;
|
||||
@@ -153,13 +153,21 @@ bool generate_certificate(const char* certfile, bool rsa)
|
||||
mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
|
||||
mbedtls_x509write_crt_set_subject_key(&crt, &key);
|
||||
mbedtls_x509write_crt_set_issuer_key(&crt, &key);
|
||||
mbedtls_x509write_crt_set_subject_name(&crt, "CN=pi.hole");
|
||||
mbedtls_x509write_crt_set_issuer_name(&crt, "CN=pi.hole");
|
||||
mbedtls_x509write_crt_set_validity(&crt, "20010101000000", "20301231235959");
|
||||
mbedtls_x509write_crt_set_basic_constraints(&crt, 0, -1);
|
||||
mbedtls_x509write_crt_set_subject_key_identifier(&crt);
|
||||
mbedtls_x509write_crt_set_authority_key_identifier(&crt);
|
||||
|
||||
// Set subject name depending on the (optionally) specified domain
|
||||
{
|
||||
char *subject_name = calloc(strlen(domain) + 4, sizeof(char));
|
||||
strcpy(subject_name, "CN=");
|
||||
strcat(subject_name, domain);
|
||||
mbedtls_x509write_crt_set_subject_name(&crt, subject_name);
|
||||
free(subject_name);
|
||||
}
|
||||
|
||||
// Export certificate in PEM format
|
||||
if((ret = mbedtls_x509write_crt_pem(&crt, cert_buffer, sizeof(cert_buffer),
|
||||
mbedtls_ctr_drbg_random, &ctr_drbg)) != 0)
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
|
||||
bool generate_certificate(const char* certfile, bool rsa);
|
||||
bool generate_certificate(const char* certfile, bool rsa, const char *domain);
|
||||
|
||||
#endif // X509_H
|
||||
|
||||
@@ -159,6 +159,11 @@
|
||||
# properly firewalled! This truly allows any traffic to be replied to and is a
|
||||
# dangerous thing to do as your Pi-hole could become an open resolver. You
|
||||
# should always ask yourself if the first option doesn't work for you as well.
|
||||
# - "NONE"
|
||||
# Do not add any configuration concerning the listening mode to the dnsmasq
|
||||
# configuration file. This is useful if you want to manually configure the
|
||||
# listening mode in auxiliary configuration files. This option is really meant
|
||||
# for advanced users only, support for this option may be limited.
|
||||
listeningMode = "LOCAL"
|
||||
|
||||
# Log DNS queries and replies to pihole.log
|
||||
|
||||
@@ -1266,7 +1266,7 @@
|
||||
@test "API authorization (without password): No login required" {
|
||||
run bash -c 'curl -s 127.0.0.1/api/auth'
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ ${lines[0]} == '{"session":{"valid":true,"totp":false,"sid":null,"validity":-1},"dns":true,"took":'*'}' ]]
|
||||
[[ ${lines[0]} == '{"session":{"valid":true,"totp":false,"sid":null,"validity":-1},"took":'*'}' ]]
|
||||
}
|
||||
|
||||
@test "API authorization: Setting password" {
|
||||
|
||||
Reference in New Issue
Block a user