Skip to content

Commit f2102a0

Browse files
authored
Merge commit from fork
Add validation for config items that shouldn't have newlines
2 parents a70b748 + 9816057 commit f2102a0

3 files changed

Lines changed: 100 additions & 6 deletions

File tree

src/config/config.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ void initConfig(struct config *conf)
410410
conf->dns.upstreams.t = CONF_JSON_STRING_ARRAY;
411411
conf->dns.upstreams.d.json = cJSON_CreateArray();
412412
conf->dns.upstreams.f = FLAG_RESTART_FTL;
413-
conf->dns.upstreams.c = validate_stub; // Type-based checking + dnsmasq syntax checking
413+
conf->dns.upstreams.c = validate_array_no_newline;
414414

415415
conf->dns.CNAMEdeepInspect.k = "dns.CNAMEdeepInspect";
416416
conf->dns.CNAMEdeepInspect.h = "Use this option to control deep CNAME inspection. Disabling it might be beneficial for very low-end devices";
@@ -537,7 +537,7 @@ void initConfig(struct config *conf)
537537
conf->dns.hostRecord.t = CONF_STRING;
538538
conf->dns.hostRecord.f = FLAG_RESTART_FTL;
539539
conf->dns.hostRecord.d.s = (char*)"";
540-
conf->dns.hostRecord.c = validate_stub; // Type-based checking + dnsmasq syntax checking
540+
conf->dns.hostRecord.c = validate_str_no_newline;
541541

542542
conf->dns.listeningMode.k = "dns.listeningMode";
543543
conf->dns.listeningMode.h = "Pi-hole interface listening modes";
@@ -641,7 +641,7 @@ void initConfig(struct config *conf)
641641
conf->dns.cache.rrtype.t = CONF_STRING;
642642
conf->dns.cache.rrtype.f = FLAG_RESTART_FTL;
643643
conf->dns.cache.rrtype.d.s = (char*)"ANY";
644-
conf->dns.cache.rrtype.c = validate_stub; // Only type-based checking
644+
conf->dns.cache.rrtype.c = validate_str_no_newline;
645645

646646
// sub-struct dns.blocking
647647
conf->dns.blocking.active.k = "dns.blocking.active";
@@ -816,7 +816,7 @@ void initConfig(struct config *conf)
816816
conf->dhcp.leaseTime.t = CONF_STRING;
817817
conf->dhcp.leaseTime.f = FLAG_RESTART_FTL;
818818
conf->dhcp.leaseTime.d.s = (char*)"";
819-
conf->dhcp.leaseTime.c = validate_stub; // Type-based checking + dnsmasq syntax checking
819+
conf->dhcp.leaseTime.c = validate_str_no_newline;
820820

821821
conf->dhcp.ipv6.k = "dhcp.ipv6";
822822
conf->dhcp.ipv6.h = "Should Pi-hole make an attempt to also satisfy IPv6 address requests (be aware that IPv6 works a whole lot different than IPv4)";
@@ -859,7 +859,7 @@ void initConfig(struct config *conf)
859859
conf->dhcp.hosts.t = CONF_JSON_STRING_ARRAY;
860860
conf->dhcp.hosts.f = FLAG_RESTART_FTL;
861861
conf->dhcp.hosts.d.json = cJSON_CreateArray();
862-
conf->dhcp.hosts.c = validate_stub; // Type-based checking + dnsmasq syntax checking
862+
conf->dhcp.hosts.c = validate_array_no_newline;
863863

864864

865865
// struct ntp
@@ -1430,7 +1430,7 @@ void initConfig(struct config *conf)
14301430
conf->misc.dnsmasq_lines.t = CONF_JSON_STRING_ARRAY;
14311431
conf->misc.dnsmasq_lines.f = FLAG_RESTART_FTL;
14321432
conf->misc.dnsmasq_lines.d.json = cJSON_CreateArray();
1433-
conf->misc.dnsmasq_lines.c = validate_stub; // Type-based checking + dnsmasq syntax checking
1433+
conf->misc.dnsmasq_lines.c = validate_array_no_newline;
14341434

14351435
conf->misc.extraLogging.k = "misc.extraLogging";
14361436
conf->misc.extraLogging.h = "Log additional information about queries and replies to pihole.log\n\n When this setting is enabled, the log has extra information at the start of each line. This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor. This setting is only effective if dns.queryLogging is enabled, too. This option is only useful for debugging and is not recommended for normal use.";

src/config/validator.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ bool validate_dns_hosts(union conf_value *val, const char *key, char err[VALIDAT
127127

128128
// Validate the dns.cnames array
129129
// Each entry needs to be a string in form "<cname>,[<cname>,]<target>[,<TTL>]"
130+
// Newline characters are not allowed in any of the entries
130131
bool validate_dns_cnames(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN])
131132
{
132133
if(!cJSON_IsArray(val->json))
@@ -174,6 +175,18 @@ bool validate_dns_cnames(union conf_value *val, const char *key, char err[VALIDA
174175
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: not a valid CNAME definition (too few elements)", key, i);
175176
return false;
176177
}
178+
179+
// Check if the string contains newline characters
180+
const unsigned int len = strlen(item->valuestring);
181+
for(unsigned int k = 0; k < len; k++)
182+
{
183+
if(item->valuestring[k] == '\n' || item->valuestring[k] == '\r')
184+
{
185+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: contains newline characters",
186+
key, i);
187+
return false;
188+
}
189+
}
177190
}
178191

179192
return true;
@@ -539,6 +552,19 @@ bool validate_dns_revServers(union conf_value *val, const char *key, char err[VA
539552
free(str);
540553
return false;
541554
}
555+
556+
// Ensure there are no newline characters in the entry
557+
const unsigned int len = strlen(item->valuestring);
558+
for(unsigned int k = 0; k < len; k++)
559+
{
560+
if(item->valuestring[k] == '\n' || item->valuestring[k] == '\r')
561+
{
562+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: contains newline characters",
563+
key, i);
564+
free(str);
565+
return false;
566+
}
567+
}
542568
}
543569

544570
// Return success
@@ -699,3 +725,69 @@ bool validate_dns_domain_or_ip(union conf_value *val, const char *key, char err[
699725
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s: neither a valid domain nor IP address", key);
700726
return false;
701727
}
728+
729+
bool validate_str_no_newline(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN])
730+
{
731+
if(val->s == NULL)
732+
{
733+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s: null string", key);
734+
return false;
735+
}
736+
737+
// Check if the string contains newline characters
738+
const unsigned int len = strlen(val->s);
739+
for(unsigned int i = 0; i < len; i++)
740+
{
741+
if(val->s[i] == '\n' || val->s[i] == '\r')
742+
{
743+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s: contains newline characters", key);
744+
return false;
745+
}
746+
}
747+
748+
return true;
749+
}
750+
751+
bool validate_array_no_newline(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN])
752+
{
753+
if(!cJSON_IsArray(val->json))
754+
{
755+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s: not an array", key);
756+
return false;
757+
}
758+
759+
for(int i = 0; i < cJSON_GetArraySize(val->json); i++)
760+
{
761+
// Get array item
762+
cJSON *item = cJSON_GetArrayItem(val->json, i);
763+
764+
// Check if it's a string
765+
if(!cJSON_IsString(item))
766+
{
767+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: not a string",
768+
key, i);
769+
return false;
770+
}
771+
772+
if(item->valuestring == NULL)
773+
{
774+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: null string",
775+
key, i);
776+
return false;
777+
}
778+
779+
// Check if the string contains newline characters
780+
const unsigned int len = strlen(item->valuestring);
781+
for(unsigned int j = 0; j < len; j++)
782+
{
783+
if(item->valuestring[j] == '\n' || item->valuestring[j] == '\r')
784+
{
785+
snprintf(err, VALIDATOR_ERRBUF_LEN, "%s[%d]: contains newline characters",
786+
key, i);
787+
return false;
788+
}
789+
}
790+
}
791+
792+
return true;
793+
}

src/config/validator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,7 @@ bool validate_dns_revServers(union conf_value *val, const char *key, char err[VA
2929
bool validate_ui_min_7_or_0(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN]);
3030
void sanitize_dns_hosts(union conf_value *val);
3131
bool validate_dns_domain_or_ip(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN]);
32+
bool validate_str_no_newline(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN]);
33+
bool validate_array_no_newline(union conf_value *val, const char *key, char err[VALIDATOR_ERRBUF_LEN]);
3234

3335
#endif // CONFIG_VALIDATOR_H

0 commit comments

Comments
 (0)