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

Add additional config validation #1773

Merged
merged 20 commits into from
Mar 12, 2024
Merged

Add additional config validation #1773

merged 20 commits into from
Mar 12, 2024

Conversation

DL6ER
Copy link
Member

@DL6ER DL6ER commented Nov 21, 2023

What does this implement/fix?

FTL is already pretty selective when it comes to accepting config values as it has a strong filter on a config value's type. For instance, your cannot set dhcp.start to a number or hostname. Similarly, you canot set dns.port to 100,000 as such a high value does not exist or -12 as negative ports don't exist either.

However, we have two config value types that do not allow strict testing: strings and arrays of strings.

This PR adds the facility to add validation callbacks to such config values so FTL will be able to check validity of those, too. I added validators for almost all string config options with only a few exceptions, e.g. dns.upstreams as dnsmasq allows upstreams to be defined by IP address or hostname, optionally with a port - we can leave checking the values to dnsmasq and will tell the user on error:

$ sudo ./pihole-FTL --config dns.upstreams '["127.0.0.1#5335","1...1#123"]'
New dnsmasq configuration is not valid (dnsmasq: Name or service not known at line 35 of /etc/pihole/dnsmasq.conf.temp: "server=1...1#123"), config remains unchanged

Some examples for validators we're adding herein:

  • dns.hosts:
    $ sudo ./pihole-FTL --config dns.hosts '["127.0.0.1"]'
    Invalid value: 1st element is not in the form "IP HOSTNAME" ("127.0.0.1")
    
    $ sudo ./pihole-FTL --config dns.hosts '["1.1.1.1 cf", "127.0.0...1 hostname"]'
    Invalid value: 2nd element is neither a valid IPv4 nor IPv6 address ("127.0.0...1")
    
  • dns.domain (similarly dns.revServer.domain, dhcp.domain, webserver.domain):
    $ sudo ./pihole-FTL --config dns.domain "----"
    Invalid value: Not a valid domain ("----")
    
  • dns.cnameRecords:
    $ sudo ./pihole-FTL --config dns.cnameRecords '["cname,,1"]'
    Invalid value: 1st element contains an empty string at position 1
    
    $ sudo ./pihole-FTL --config dns.cnameRecords '["cname"]'
    Invalid value: 1st element is not a valid CNAME definition
    
  • dns.revServer.cidr:
    $ sudo ./pihole-FTL --config dns.revServer.cidr "1.1.1.1/55"
    New dnsmasq configuration is not valid (dnsmasq: bad IPv4 prefix length at line 82 of /etc/pihole/dnsmasq.conf.temp: "rev-server=1.1.1.1/55,192.168.2.1"), config remains unchanged
    
    $ sudo ./pihole-FTL --config dns.revServer.cidr "1.1.1..1/24"
    Invalid value: Not a valid IPv4 nor IPv6 address ("1.1.1..1")
    
  • dns.revServer.target
    $ sudo ./pihole-FTL --config dns.revServer.target "1.1.1..1"
    Invalid value: Not a valid IPv4 nor IPv6 address ("1.1.1..1")
    
    $ sudo ./pihole-FTL --config dns.revServer.target "1.1.1.1#500000"
    Invalid value: Not a valid port ("500000")
    
  • webserver.tls.cert (similarly all paths in files):
    $ sudo ./pihole-FTL --config webserver.tls.cert "/etc/pihole/tls.pem?"
    Invalid value: Not a valid file path ("/etc/pihole/tls.pem?")
    

Related issue or feature (if applicable): N/A

Pull request in docs with documentation (if applicable): N/A


By submitting this pull request, I confirm the following:

  1. I have read and understood the contributors guide, as well as this entire template. I understand which branch to base my commits and Pull Requests against.
  2. I have commented my proposed changes within the code.
  3. I am willing to help maintain this change if there are issues with it later.
  4. It is compatible with the EUPL 1.2 license
  5. I have squashed any insignificant commits. (git rebase)

Checklist:

  • The code change is tested and works locally.
  • I based my code and PRs against the repositories developmental branch.
  • I signed off all commits. Pi-hole enforces the DCO for all contributions
  • I signed all my commits. Pi-hole requires signatures to verify authorship
  • I have read the above and my PR is ready for review.

Copy link
Member

@yubiuser yubiuser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment (in the source code), which items are validated by dnsmasq. Otherwise it's hard to judge if something was forgotten or left out on purpose.

@@ -767,6 +767,20 @@ static int api_config_patch(struct ftl_conn *api)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the line above we have config_changed=true;
> should this be placed after the new value validation? We reject the new config when the value is invalid in the end.

Otherwise manual editing of pihole.toml can still add invalid entries.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter. If validation fails, this function will free the temporary newconf in line 776 below and return. Nobody will ever look at the value of config_changed

@DL6ER
Copy link
Member Author

DL6ER commented Nov 22, 2023

Could you please add a comment (in the source code), which items are validated by dnsmasq. Otherwise it's hard to judge if something was forgotten or left out on purpose.

dnsmasq validates everything causing a config rewrite (settings marked with FLAG_RESTART_FTL) but we are not particularly happy how it does this for these two: dns.cnameRecords and dns.hosts.
dnsmasq accepts an empty target as a CNAME to the root zone. I don't think this is wrong as such bu it seems we don't want this to be valid. dnsmasq also "accepts" incomplete HOSTS records by simply ignoring lines not in the correct format.

@DL6ER
Copy link
Member Author

DL6ER commented Nov 22, 2023

Should one-character domains be considered valid? In the context of valid_domain() a minimum domain length of two characters is required.

// The last label must be at least 2 characters long
// (len-1) because we start counting from zero
if((len - 1) - last_dot < 2)
return false;

@yubiuser
Copy link
Member

I think it should be two characters for external domains, but accept single characters for local hostnames.

Someone might have a.lan, b.lan,...

@DL6ER
Copy link
Member Author

DL6ER commented Nov 22, 2023

Those are FQDN. The length limitation applies only to the last label (lan) in your example above, a would be rejected, a.lan is fine

Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link

Conflicts have been resolved.

Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link

Conflicts have been resolved.

Copy link

github-actions bot commented Jan 6, 2024

This pull request has conflicts, please resolve those before we can evaluate the pull request.

DL6ER added 2 commits January 21, 2024 20:16
…log error that will fail the CI tests. This will help ensuring we won't forget to add validators for PRs that are merged in parallel or new config options added in the future

Signed-off-by: DL6ER <[email protected]>
…hen a user tries to set multiple values at once (e.g. via the web UI)

Signed-off-by: DL6ER <[email protected]>
@DL6ER
Copy link
Member Author

DL6ER commented Jan 22, 2024

The last commit adds explicit places where the issue happens:

Screenshot from 2024-01-22 13-20-56
Screenshot from 2024-01-22 13-20-46

Copy link

github-actions bot commented Feb 9, 2024

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link

Conflicts have been resolved.

Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link

Conflicts have been resolved.

Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link

Conflicts have been resolved.

@DL6ER
Copy link
Member Author

DL6ER commented Feb 11, 2024

New examples:

tre,192.168.2.0/24,192.168.2.1,fritz.box

Screenshot from 2024-02-11 06-57-16

true,692.168.2.0/24,192.168.2.1,fritz.box

Screenshot from 2024-02-11 07-01-39

true,192.168.2.0/245,192.168.2.1,fritz.box

Screenshot from 2024-02-11 07-01-54

true,192.168.2.0/24,192.168.2.1#44455585,fritz.box

Screenshot from 2024-02-11 07-03-14

@PromoFaux
Copy link
Member

This all looks good, do you plan on adding some unit tests?

Copy link
Member

@PromoFaux PromoFaux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff, even greater with tests!

@DL6ER DL6ER merged commit 1bb74b3 into development-v6 Mar 12, 2024
17 checks passed
@DL6ER DL6ER deleted the new/validator branch March 12, 2024 19:29
@PromoFaux PromoFaux mentioned this pull request Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants