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

[BUG] Resolver uses nameserver commented out in /etc/resolv.conf #237

Closed
grembo opened this issue May 3, 2024 · 5 comments
Closed

[BUG] Resolver uses nameserver commented out in /etc/resolv.conf #237

grembo opened this issue May 3, 2024 · 5 comments

Comments

@grembo
Copy link

grembo commented May 3, 2024

TL;DR

Comment parsing in /etc/resolv.conf is broken since 889f7c7

How to reproduce

Create a basic resolv.conf containing comments:

cat<<EOF >/etc/resolv.conf
# x

# nameserver 8.8.8.8
EOF

Then run drill on some zone:

drill wikipedia.org

Expected outcome

Since there are no nameservers configured, this outcome would be expected:

Error: error sending query: No (valid) nameservers defined in the resolver

Actual outcome

The commented out nameserver entry is used:

;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 17996
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; wikipedia.org.	IN	A

;; ANSWER SECTION:
wikipedia.org.	77	IN	A	185.15.59.224

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 20 msec
;; SERVER: 8.8.8.8
;; WHEN: Fri May  3 15:40:07 2024
;; MSG SIZE  rcvd: 47

Analysis

Commit 889f7c7 introduced this change:

diff --git a/parse.c b/parse.c
index 3c737620..9698ba71 100644
--- a/parse.c
+++ b/parse.c
@@ -187,6 +187,9 @@ ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed
                if (c != '\0' && c != '\n') {
                        *t++ = c;
                }
+               if (c == '\n' && line_nr) {
+                       *line_nr = *line_nr + 1;
+               }
                if (c == '\\' && prev_c == '\\')
                        prev_c = 0;
                else    prev_c = c;

Which breaks comment handling in resolver.c, which only removes characters until the end of line, in case line_nr doesn't change:

                if (word[0] == '#') {
                        word[0]='x';
                        if(oldline == *line_nr) {
                                /* skip until end of line */
                                int c;
                                do {
                                        c = fgetc(myfp);
                                } while(c != EOF && c != '\n');
                                if(c=='\n') (*line_nr)++;
                        }
                        /* and read next to prepare for further parsing */
                        oldline = *line_nr;
                        continue;
                }

Potential Fixes

The parser isn't necessarily the kind of code one just jumps into and reasons about, yet the three suggestions below worked for my limited use case:

  1. Rollback 889f7c7 (from the commit it's unclear, if it fixed a cosmetic or a functional issue)
  2. Make ldns_fget_token_l_st understand comments starting with # (unclear which side-effects this might have)
diff --git a/parse.c b/parse.c
index 9698ba71..a2478f66 100644
--- a/parse.c
+++ b/parse.c
@@ -98,7 +98,7 @@ ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed
                }
 
                /* do something with comments ; */
-               if (c == ';' && quoted == 0) {
+               if ((c == ';' || c == '#') && quoted == 0) {
                        if (prev_c != '\\') {
                                com = 1;
                        }
  1. Patch resolver.c's comment handling (again, might have unwanted side effects):
diff --git a/resolver.c b/resolver.c
index f9ec65a5..e8921dbc 100644
--- a/resolver.c
+++ b/resolver.c
@@ -815,14 +815,12 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
                /* check comments */
                if (word[0] == '#') {
                         word[0]='x';
-                        if(oldline == *line_nr) {
                                 /* skip until end of line */
                                 int c;
                                 do {
                                         c = fgetc(myfp);
                                 } while(c != EOF && c != '\n');
                                 if(c=='\n') (*line_nr)++;
-                        }
                        /* and read next to prepare for further parsing */
                         oldline = *line_nr;
                        continue;

Real life resolv.conf

This is the configuration where we first encountered issues (it would request a local zone from google DNS and fail with NXDOMAIN, even though we would expect the call to be handled by unbound running locally)

# Generated by resolvconf
# nameserver 192.168.1.1

# nameserver 8.8.8.8
nameserver 127.0.0.1
options edns0
@grembo grembo changed the title [BUG] Parsing resolv.conf skips comments [BUG] Parsing resolv.conf uses commented out nameserver May 4, 2024
@grembo
Copy link
Author

grembo commented May 4, 2024

@grembo grembo changed the title [BUG] Parsing resolv.conf uses commented out nameserver [BUG] Resolver uses nameserver commented out in /etc/resolv.conf May 4, 2024
@grembo
Copy link
Author

grembo commented May 4, 2024

Hopefully found a title that makes more sense now 😄

wtoorop added a commit that referenced this issue May 7, 2024
This /etc/resolv.conf:
    # x

    # nameserver 8.8.8.8

Still configured 8.8.8.8 as nameserver, because the comment detection in `ldns_resolver_new_frm_fp_l()` didn't anticipate empty lines before the comment.
This fix removed all comment handling from `ldns_resolver_new_frm_fp_l()`. Instead a new function is introduced `ldns_fget_token_l_resolv_conf()` that skips comments that start with '#' and ';'. The old `ldns_fget_token_l()` (that is used for zonefiles too) still accepts only ';' for comments.
@wtoorop
Copy link
Member

wtoorop commented May 7, 2024

  1. Make ldns_fget_token_l_st understand comments starting with # (unclear which side-effects this might have)

Thank you @grembo . I prefer that one, and then remove all comment handling from resolver.c. I just added a bit more (in PR #238) so that zonefile parsing does not accept comments to start with '#' too.

wtoorop added a commit that referenced this issue May 15, 2024
@grembo
Copy link
Author

grembo commented May 15, 2024

Fixed by #238, thank you guys!

@grembo grembo closed this as completed May 15, 2024
@wtoorop
Copy link
Member

wtoorop commented May 15, 2024

And thank you for reporting!

@dag-erling I've put a bugfix release on the calender for June.

freebsd-git pushed a commit to freebsd/freebsd-ports that referenced this issue Jul 22, 2024
The most prominent fix is for the bug where ldns would, under certain
conditions, use a commented out resolver in /etc/resolv.conf:
NLnetLabs/ldns#237

Changelog:
https://github.com/NLnetLabs/ldns/blob/1.8.4/Changelog

PR:	280404 278721
MFH:	2024Q3
freebsd-git pushed a commit to freebsd/freebsd-ports that referenced this issue Jul 22, 2024
The most prominent fix is for the bug where ldns would, under certain
conditions, use a commented out resolver in /etc/resolv.conf:
NLnetLabs/ldns#237

Changelog:
https://github.com/NLnetLabs/ldns/blob/1.8.4/Changelog

PR:	280404 278721
MFH:	2024Q3
(cherry picked from commit 7fe9f43)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants