Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/privacy levels regex filtering #417

Merged
merged 5 commits into from
Nov 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions FTL.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ enum { MODE_IP, MODE_NX, MODE_NULL, MODE_IP_NODATA_AAAA };
enum { REGEX_UNKNOWN, REGEX_BLOCKED, REGEX_NOTBLOCKED };
enum { BLOCKING_DISABLED, BLOCKING_ENABLED, BLOCKING_UNKNOWN };

// Privacy mode constants
#define HIDDEN_DOMAIN "hidden"
#define HIDDEN_CLIENT "0.0.0.0"

// Static structs
typedef struct {
const char* conf;
Expand Down Expand Up @@ -146,7 +150,7 @@ typedef struct {
int DBinterval;
int port;
int maxlogage;
int privacylevel;
unsigned char privacylevel;
bool ignore_localhost;
unsigned char blockingmode;
bool regex_debugmode;
Expand All @@ -167,7 +171,7 @@ typedef struct {
bool db;
int id; // the ID is a (signed) int in dnsmasq, so no need for a long int here
bool complete;
bool private;
unsigned char privacylevel;
unsigned long response; // saved in units of 1/10 milliseconds (1 = 0.1ms, 2 = 0.2ms, 2500 = 250.0ms, etc.)
unsigned char reply;
unsigned char dnssec;
Expand Down
30 changes: 17 additions & 13 deletions api.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void getStats(int *sock)
// Send individual reply type counters
ssend(*sock, "reply_NODATA %i\nreply_NXDOMAIN %i\nreply_CNAME %i\nreply_IP %i\n",
counters.reply_NODATA, counters.reply_NXDOMAIN, counters.reply_CNAME, counters.reply_IP);
ssend(*sock, "privacy_level %i\n", config.privacylevel);
}
else
{
Expand Down Expand Up @@ -264,7 +265,7 @@ void getTopDomains(char *client_message, int *sock)
continue;

// Hidden domain, probably due to privacy level. Skip this in the top lists
if(strcmp(domains[j].domain, "hidden") == 0)
if(strcmp(domains[j].domain, HIDDEN_DOMAIN) == 0)
continue;

if(blocked && showblocked && domains[j].blockedcount > 0)
Expand Down Expand Up @@ -403,7 +404,7 @@ void getTopClients(char *client_message, int *sock)
continue;

// Hidden client, probably due to privacy level. Skip this in the top lists
if(strcmp(clients[j].ip, "0.0.0.0") == 0)
if(strcmp(clients[j].ip, HIDDEN_CLIENT) == 0)
continue;

// Only return name if available
Expand Down Expand Up @@ -760,7 +761,7 @@ void getAllQueries(char *client_message, int *sock)
{
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
// Check if this query has been create while in maximum privacy mode
if(queries[i].private) continue;
if(queries[i].privacylevel >= PRIVACY_MAXIMUM) continue;

validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);
Expand Down Expand Up @@ -808,13 +809,17 @@ void getAllQueries(char *client_message, int *sock)
continue;
}

char *domain = domains[queries[i].domainID].domain;
// Ask subroutine for domain. It may return "hidden" depending on
// the privacy settings at the time the query was made
char *domain = getDomainString(i);
// Similarly for the client
char *client;
if(clients[queries[i].clientID].name != NULL &&
strlen(clients[queries[i].clientID].name) > 0)
strlen(clients[queries[i].clientID].name) > 0 &&
queries[i].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
client = clients[queries[i].clientID].name;
else
client = clients[queries[i].clientID].ip;
client = getClientIPString(i);

unsigned long delay = queries[i].response;
// Check if received (delay should be smaller than 30min)
Expand Down Expand Up @@ -857,11 +862,6 @@ void getRecentBlocked(char *client_message, int *sock)
{
int i, num=1;

// Exit before processing any data if requested via config setting
get_privacy_level(NULL);
if(config.privacylevel >= PRIVACY_HIDE_DOMAINS)
return;

// Test for integer that specifies number of entries to be shown
if(sscanf(client_message, "%*[^(](%i)", &num) > 0) {
// User wants a different number of requests
Expand All @@ -881,9 +881,13 @@ void getRecentBlocked(char *client_message, int *sock)
{
found++;

// Ask subroutine for domain. It may return "hidden" depending on
// the privacy settings at the time the query was made
char *domain = getDomainString(i);

if(istelnet[*sock])
ssend(*sock,"%s\n", domains[queries[i].domainID].domain);
else if(!pack_str32(*sock, domains[queries[i].domainID].domain))
ssend(*sock,"%s\n", domain);
else if(!pack_str32(*sock, domain))
return;
}

Expand Down
8 changes: 4 additions & 4 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,11 @@ void get_privacy_level(FILE *fp)
if(buffer != NULL && sscanf(buffer, "%i", &value) == 1)
{
// Check for change and validity of privacy level (set in FTL.h)
if(value != config.privacylevel &&
value >= PRIVACY_SHOW_ALL &&
value <= PRIVACY_NOSTATS)
if(value >= PRIVACY_SHOW_ALL &&
value <= PRIVACY_NOSTATS &&
value > config.privacylevel)
{
logg("Notice: Changing privacy level from %i to %i", config.privacylevel, value);
logg("Notice: Increasing privacy level from %i to %i", config.privacylevel, value);
config.privacylevel = value;
}
}
Expand Down
10 changes: 5 additions & 5 deletions database.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,8 @@ void save_to_DB(void)

// Memory checks
validate_access("queries", i, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("domains", queries[i].domainID, true, __LINE__, __FUNCTION__, __FILE__);
validate_access("clients", queries[i].clientID, true, __LINE__, __FUNCTION__, __FILE__);

if(queries[i].private)
if(queries[i].privacylevel >= PRIVACY_MAXIMUM)
{
// Skip, we never store nor count queries recorded
// while have been in maximum privacy mode in the database
Expand All @@ -413,10 +411,12 @@ void save_to_DB(void)
sqlite3_bind_int(stmt, 3, queries[i].status);

// DOMAIN
sqlite3_bind_text(stmt, 4, domains[queries[i].domainID].domain, -1, SQLITE_TRANSIENT);
char *domain = getDomainString(i);
sqlite3_bind_text(stmt, 4, domain, -1, SQLITE_TRANSIENT);

// CLIENT
sqlite3_bind_text(stmt, 5, clients[queries[i].clientID].ip, -1, SQLITE_TRANSIENT);
char *client = getClientIPString(i);
sqlite3_bind_text(stmt, 5, client, -1, SQLITE_TRANSIENT);

// FORWARD
if(queries[i].status == QUERY_FORWARDED && queries[i].forwardID > -1)
Expand Down
26 changes: 26 additions & 0 deletions datastructure.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,29 @@ bool isValidIPv6(const char *addr)
struct sockaddr_in6 sa;
return inet_pton(AF_INET6, addr, &(sa.sin6_addr)) != 0;
}

// Privacy-level sensitive subroutine that returns the domain name
// only when appropriate for the requested query
char *getDomainString(int queryID)
{
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS)
{
validate_access("domains", queries[queryID].domainID, true, __LINE__, __FUNCTION__, __FILE__);
return domains[queries[queryID].domainID].domain;
}
else
return HIDDEN_DOMAIN;
}

// Privacy-level sensitive subroutine that returns the client IP
// only when appropriate for the requested query
char *getClientIPString(int queryID)
{
if(queries[queryID].privacylevel < PRIVACY_HIDE_DOMAINS_CLIENTS)
{
validate_access("clients", queries[queryID].clientID, true, __LINE__, __FUNCTION__, __FILE__);
return clients[queries[queryID].clientID].ip;
}
else
return HIDDEN_CLIENT;
}
6 changes: 6 additions & 0 deletions dnsmasq/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,12 @@ int cache_make_stat(struct txt_record *t)
break;
#endif

/* Pi-hole modification */
case TXT_PRIVACYLEVEL:
sprintf(buff+1, "%d", *pihole_privacylevel);
break;
/* -------------------- */

case TXT_STAT_SERVERS:
/* sum counts from different records for same server */
for (serv = daemon->servers; serv; serv = serv->next)
Expand Down
3 changes: 3 additions & 0 deletions dnsmasq/dnsmasq.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ struct naptr {
#define TXT_STAT_HITS 5
#define TXT_STAT_AUTH 6
#define TXT_STAT_SERVERS 7
/* Pi-hole modification */
#define TXT_PRIVACYLEVEL 123
/************************/
#endif

struct txt_record {
Expand Down
Loading