Redirect PH7 errors into pihole-FTL.log (instead of showing in the browser output) and define gethostname() PHP function.

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2020-06-01 12:06:35 +02:00
parent cf5f3ef464
commit 67a0395390
24 changed files with 181 additions and 101 deletions

View File

@ -156,6 +156,8 @@ add_custom_target(
add_executable(pihole-FTL
${sources}
$<TARGET_OBJECTS:api>
$<TARGET_OBJECTS:webserver>
$<TARGET_OBJECTS:ph7_ext>
$<TARGET_OBJECTS:civetweb>
$<TARGET_OBJECTS:cJSON>
$<TARGET_OBJECTS:ph7>
@ -197,6 +199,7 @@ install(TARGETS pihole-FTL
install(CODE "execute_process(COMMAND ${SETCAP} CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+eip ${CMAKE_INSTALL_PREFIX}/bin/pihole-FTL)")
add_subdirectory(api)
add_subdirectory(webserver)
add_subdirectory(civetweb)
add_subdirectory(cJSON)
add_subdirectory(ph7)

View File

@ -14,17 +14,12 @@ set(sources
dns.h
ftl.c
ftl.h
http-common.c
http-common.h
json_macros.h
routes.c
routes.h
settings.c
stats_database.c
stats.c
version.c
webserver.c
ph7.c
)
add_library(api OBJECT ${sources})

View File

@ -9,9 +9,9 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
#include "log.h"
#include "config.h"
// read_setupVarsconf()

View File

@ -12,11 +12,10 @@
// counters
#include "shmem.h"
#include "dns.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
#include "database/gravity-db.h"
#include "api/http-common.h"
#include "log.h"
// {s,g}et_blockingstatus()
#include "setupVars.h"

View File

@ -9,10 +9,10 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "ftl.h"
#include "json_macros.h"
#include "datastructure.h"
// get_FTL_version()
#include "log.h"

View File

@ -11,8 +11,8 @@
#include "../FTL.h"
// struct mg_connection
#include "../civetweb/civetweb.h"
#include "http-common.h"
#include "json_macros.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "../shmem.h"

View File

@ -9,9 +9,9 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
// get_FTL_db_filesize()
#include "files.h"
// get_sqlite3_version()

View File

@ -9,9 +9,9 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
#include "shmem.h"
#include "datastructure.h"
// read_setupVarsconf()

View File

@ -9,9 +9,9 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
#include "shmem.h"
#include "datastructure.h"
// logg()

View File

@ -9,9 +9,9 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "http-common.h"
#include "../webserver/http-common.h"
#include "../webserver/json_macros.h"
#include "routes.h"
#include "json_macros.h"
// get_FTL_version()
#include "log.h"
#include "version.h"

View File

@ -33,7 +33,7 @@
// global variable daemonmode
#include "args.h"
// http_init()
#include "api/webserver.h"
#include "webserver/webserver.h"
// add_to_dnsmasq_log_buffer()
#include "api/ftl.h"

View File

@ -24,7 +24,7 @@
#include "database/gravity-db.h"
#include "timers.h"
// http_terminate()
#include "api/webserver.h"
#include "webserver/webserver.h"
char * username;
bool needGC = false;

View File

@ -125,6 +125,9 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/******************************* Pi-hole modification ******************************/
extern void logg(const char* format, ...) __attribute__ ((format (gnu_printf, 1, 2)));
/***********************************************************************************/
/* $SymiscID: ph7.h v2.1 UNIX|WIN32/64 2012-09-15 09:43 stable <chm@symisc.net> $ */
#include <stdarg.h> /* needed for the definition of va_list */
/*
@ -5001,24 +5004,14 @@ static sxi32 VmThrowException(ph7_vm *pVm,ph7_class_instance *pThis);
/*
* Consume a generated run-time error message by invoking the VM output
* consumer callback.
* ATTENTION: MODIFIED BY PI-HOLE
*/
static sxi32 VmCallErrorHandler(ph7_vm *pVm,SyBlob *pMsg)
{
ph7_output_consumer *pCons = &pVm->sVmConsumer;
sxi32 rc = SXRET_OK;
/* Append a new line */
#ifdef __WINNT__
SyBlobAppend(pMsg,"\r\n",sizeof("\r\n")-1);
#else
SyBlobAppend(pMsg,"\n",sizeof(char));
#endif
/* Invoke the output consumer callback */
rc = pCons->xConsumer(SyBlobData(pMsg),SyBlobLength(pMsg),pCons->pUserData);
if( pCons->xConsumer != VmObConsumer ){
/* Increment output length */
pVm->nOutputLen += SyBlobLength(pMsg);
}
return rc;
logg("PH7 Error: %.*s", SyBlobLength(pMsg), SyBlobData(pMsg));
return SXRET_OK;
}
/*
* Throw a run-time error and invoke the supplied VM output consumer callback.

View File

@ -0,0 +1,26 @@
# Pi-hole: A black hole for Internet advertisements
# (c) 2020 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# FTL Engine
# /src/webserver/CMakeList.txt
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
set(sources
http-common.c
http-common.h
webserver.c
webserver.h
ph7.c
ph7.h
json_macros.h
)
add_library(webserver OBJECT ${sources})
add_dependencies(webserver gen_version)
target_compile_options(webserver PRIVATE ${EXTRAWARN})
target_include_directories(webserver PRIVATE ${PROJECT_SOURCE_DIR}/src)
add_subdirectory(ph7_ext)

View File

@ -9,7 +9,6 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "routes.h"
#include "http-common.h"
#include "../config.h"
#include "../log.h"

View File

@ -1,5 +1,5 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2019 Pi-hole, LLC (https://pi-hole.net)
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
@ -27,6 +27,10 @@
// open
#include <fcntl.h>
// Pi-hole PH7 extensions
#define PH7_CORE
#include "ph7_ext/extensions.h"
// PH7 virtual machine engine
static ph7 *pEngine; /* PH7 engine */
static ph7_vm *pVm; /* Compiled PHP program */
@ -34,15 +38,8 @@ static ph7_vm *pVm; /* Compiled PHP program */
static char *webroot_with_home = NULL;
static char *webroot_with_home_and_scripts = NULL;
/*
* VM output consumer callback.
* Each time the virtual machine generates some outputs, the following
* function gets called by the underlying virtual machine to consume
* the generated output.
* This function is registered later via a call to ph7_vm_config()
* with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
*/
static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *pUserData /* Unused */)
static int PH7_error_report(const void *pOutput, unsigned int nOutputLen,
void *pUserData /* Unused */)
{
// Log error message, strip trailing newline character if any
if(((const char*)pOutput)[nOutputLen-1] == '\n')
@ -53,10 +50,7 @@ static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *p
int ph7_handler(struct mg_connection *conn, void *cbdata)
{
int rc;
const void *pOut;
unsigned int nLen;
/* Handler may access the request info using mg_get_request_info */
const struct mg_request_info * req_info = mg_get_request_info(conn);
@ -73,14 +67,13 @@ int ph7_handler(struct mg_connection *conn, void *cbdata)
logg("Full path of PHP script: %s", full_path);
// Compile PHP script into byte-code
// This usually takes only 1-2 msec even for long scripts
// (measrued on a Raspberry Pi 3), so there is little
// point in buffering the compiled script somewhere
// This usually takes only 1-2 msec even for larger scripts on a Raspberry
// Pi 3, so there is little point in buffering the compiled script
rc = ph7_compile_file(
pEngine, /* PH7 Engine */
pEngine, /* PH7 Engine */
full_path, /* Path to the PHP file to compile */
&pVm, /* OUT: Compiled PHP program */
0 /* IN: Compile flags */
&pVm, /* OUT: Compiled PHP program */
0 /* IN: Compile flags */
);
/* Report script run-time errors */
@ -93,13 +86,16 @@ int ph7_handler(struct mg_connection *conn, void *cbdata)
if( rc != PH7_OK ){ /* Compile error */
if( rc == PH7_IO_ERR )
{
logg("IO error while opening the target file");
logg("IO error while opening the target file (%s)", full_path);
// Fall back to HTTP server to handle the 404 event
return 0;
}
else if( rc == PH7_VM_ERR )
{
logg("VM initialization error");
return 0;
// Mark file as processes - this prevents the HTTP server
// from printing the raw PHP source code to the user
return 1;
}
else
{
@ -117,50 +113,46 @@ int ph7_handler(struct mg_connection *conn, void *cbdata)
/* zErrLog is null terminated */
logg("PH7 compile error: %s", zErrLog);
}
// Mark file as processes - this prevents the HTTP server
// from printing the raw PHP source code to the user
return 1;
}
}
// Register Pi-hole's PH7 extensions (defined in subdirectory "ph7_ext/")
for(unsigned int i = 0; i < sizeof(aFunc)/sizeof(aFunc[0]); i++ )
{
rc = ph7_create_function(pVm, aFunc[i].zName, aFunc[i].xProc, NULL /* NULL: No private data */);
if( rc != PH7_OK ){
logg("Error while registering foreign function %s()", aFunc[i].zName);
}
}
// Execute virtual machine
rc = ph7_vm_exec(pVm,0);
if( rc != PH7_OK )
{
logg("VM execution error");
return 0;
// Mark file as processes - this prevents the HTTP server
// from printing the raw PHP source code to the user
return 1;
}
/*
* Now we have our script compiled,it's time to configure our VM.
* We will install the VM output consumer callback defined above
* so that we can consume the VM output and redirect it to STDOUT.
*/
/* Extract the output */
// Extract and send the output (if any)
const void *pOut = NULL;
unsigned int nLen = 0u;
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_EXTRACT_OUTPUT, &pOut, &nLen);
if(nLen > 0)
{
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
mg_write(conn, pOut, nLen);
}
#if 0
const char *zErrLog;
int niLen;
/* Extract error log */
ph7_config(
pEngine,
PH7_CONFIG_ERR_LOG,
&zErrLog, /* First arg*/
&niLen /* Second arg */
);
if( niLen > 0 ){
logg("%s", zErrLog); /* Output*/
}
#endif
// Reset and release the virtual machine
ph7_vm_reset(pVm);
ph7_vm_release(pVm);
// Processed the file
return 1;
}
@ -172,24 +164,15 @@ void init_ph7(void)
return;
}
/* Set an error log consumer callback. This callback [Output_Consumer()] will
* redirect all compile-time error messages to STDOUT.
*/
ph7_config(pEngine,PH7_VM_CONFIG_OUTPUT,
Output_Consumer, // Error log consumer
0 // NULL: Callback Private data
);
/*
ph7_config(pEngine,PH7_CONFIG_ERR_OUTPUT,
Output_Consumer, // Error log consumer
0 // NULL: Callback Private data
);*/
// Set an error log consumer callback. This callback will
// receive all compile-time error messages to
ph7_config(pEngine,PH7_VM_CONFIG_OUTPUT, PH7_error_report, NULL /* NULL: No private data */);
// Prepare include paths
// var/www/html/admin (may be different due to user configuration)
const size_t webroot_len = strlen(httpsettings.webroot);
const size_t webhome_len = strlen(httpsettings.webhome);
webroot_with_home = calloc(webroot_len+webhome_len+1, sizeof(char));
webroot_with_home = calloc(webroot_len + webhome_len + 1u, sizeof(char));
strcpy(webroot_with_home, httpsettings.webroot);
strcpy(webroot_with_home + webroot_len, httpsettings.webhome);
webroot_with_home[webroot_len + webhome_len] = '\0';
@ -198,7 +181,7 @@ void init_ph7(void)
const char scripts_dir[] = "/scripts/pi-hole/php";
size_t scripts_dir_len = sizeof(scripts_dir);
size_t webroot_with_home_len = strlen(webroot_with_home);
webroot_with_home_and_scripts = calloc(webroot_with_home_len+scripts_dir_len+1, sizeof(char));
webroot_with_home_and_scripts = calloc(webroot_with_home_len + scripts_dir_len + 1u, sizeof(char));
strcpy(webroot_with_home_and_scripts, webroot_with_home);
strcpy(webroot_with_home_and_scripts + webroot_with_home_len, scripts_dir);
webroot_with_home_and_scripts[webroot_with_home_len + scripts_dir_len] = '\0';
@ -206,7 +189,6 @@ void init_ph7(void)
void ph7_terminate(void)
{
ph7_vm_release(pVm);
ph7_release(pEngine);
free(webroot_with_home);
free(webroot_with_home_and_scripts);

View File

@ -14,5 +14,4 @@ void init_ph7(void);
void ph7_terminate(void);
int ph7_handler(struct mg_connection *conn, void *cbdata);
#endif // PH7_H

View File

@ -0,0 +1,19 @@
# Pi-hole: A black hole for Internet advertisements
# (c) 2020 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# FTL Engine
# /src/webserver/CMakeList.txt
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
set(sources
extensions.h
gethostname.c
)
add_library(ph7_ext OBJECT ${sources})
add_dependencies(ph7_ext gen_version)
target_compile_options(ph7_ext PRIVATE ${EXTRAWARN})
target_include_directories(ph7_ext PRIVATE ${PROJECT_SOURCE_DIR}/src)

View File

@ -0,0 +1,27 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* PH7 extension prototypes
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#ifndef PH7_EXT_H
#define PH7_EXT_H
// Function prototypes
int gethostname_impl(ph7_context *pCtx, int argc, ph7_value **argv);
#ifdef PH7_CORE // Include this section only in ../ph7.c
// Container for the foreign functions defined above.
// These functions will be registered later using a call
// to [ph7_create_function()].
static const struct foreign_func {
const char *zName; /* Name of the foreign function*/
int (*xProc)(ph7_context *, int, ph7_value **); /* Pointer to the C function performing the computation*/
}aFunc[] = {
{"gethostname", gethostname_impl}
};
#endif // PH7_CORE
#endif // PH7_EXT_H

View File

@ -0,0 +1,38 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2020 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* FTL Engine
* PH7 extension: gethostname()
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
#include "../../ph7/ph7.h"
#include "extensions.h"
#include <string.h>
#include <unistd.h>
int gethostname_impl(ph7_context *pCtx, int argc, ph7_value **argv)
{
// We do not accept input arguments here
if(argc != 0)
{
// Invalid argument,throw a warning and return FALSE.
ph7_context_throw_error(pCtx, PH7_CTX_WARNING, "No arguments allowed");
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
// Get host name
char name[256];
if(gethostname(name, sizeof(name)) != 0)
{
strcpy(name, "N/A");
}
ph7_result_string(pCtx, name, strlen(name));
/* All done */
return PH7_OK;
}

View File

@ -9,7 +9,7 @@
* Please see LICENSE file for your rights under this license. */
#include "FTL.h"
#include "routes.h"
#include "../api/routes.h"
// send_http()
#include "http-common.h"
// struct httpsettings