From 6ea0e6f273dc8071a381735b71acb21955b87a27 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Tue, 16 Jan 2018 19:16:09 -0500 Subject: added support for IPv6 DNS configuration - #1722 --- src/firejail/firejail.h | 8 +++++--- src/firejail/fs_hostname.c | 10 ++++++---- src/firejail/main.c | 20 ++++++++++++-------- src/firejail/network.c | 15 +++++++++++++++ src/firejail/profile.c | 21 +++++++++++++-------- src/firejail/sandbox.c | 14 ++++++++------ test/environment/dns.exp | 10 +++++++++- test/environment/dns.profile | 1 + test/utils/dns-print.exp | 6 +++++- 9 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index a76d2795d..e96a5d63e 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -240,9 +240,10 @@ typedef struct config_t { Interface interface1; Interface interface2; Interface interface3; - uint32_t dns1; // up to 3 IP addresses for dns servers - uint32_t dns2; - uint32_t dns3; + char *dns1; // up to 3 IP (v4/v6) addresses for dns servers + char *dns2; + char *dns3; + char *dns4; // seccomp char *seccomp_list;// optional seccomp list on top of default filter @@ -409,6 +410,7 @@ void net_dns_print(pid_t pid); void network_main(pid_t child); // network.c +int check_ip46_address(const char *addr); void net_if_up(const char *ifname); void net_if_down(const char *ifname); void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu); diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 137686572..fd823b812 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c @@ -89,7 +89,7 @@ errexit: } void fs_resolvconf(void) { - if (cfg.dns1 == 0) + if (cfg.dns1 == NULL) return; if (arg_debug) @@ -164,11 +164,13 @@ void fs_resolvconf(void) { } if (cfg.dns1) - fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); + fprintf(fp, "nameserver %s\n", cfg.dns1); if (cfg.dns2) - fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); + fprintf(fp, "nameserver %s\n", cfg.dns2); if (cfg.dns3) - fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); + fprintf(fp, "nameserver %s\n", cfg.dns3); + if (cfg.dns4) + fprintf(fp, "nameserver %s\n", cfg.dns4); // mode and owner SET_PERMS_STREAM(fp, 0, 0, 0644); diff --git a/src/firejail/main.c b/src/firejail/main.c index bc6eb8219..b2b4fe525 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -2064,20 +2064,24 @@ int main(int argc, char **argv) { } #endif else if (strncmp(argv[i], "--dns=", 6) == 0) { - uint32_t dns; - if (atoip(argv[i] + 6, &dns)) { - fprintf(stderr, "Error: invalid DNS server IP address\n"); - return 1; + if (check_ip46_address(argv[i] + 6) == 0) { + fprintf(stderr, "Error: invalid DNS server IPv4 or IPv6 address\n"); + exit(1); } + char *dns = strdup(argv[i] + 6); + if (!dns) + errExit("strdup"); - if (cfg.dns1 == 0) + if (cfg.dns1 == NULL) cfg.dns1 = dns; - else if (cfg.dns2 == 0) + else if (cfg.dns2 == NULL) cfg.dns2 = dns; - else if (cfg.dns3 == 0) + else if (cfg.dns3 == NULL) cfg.dns3 = dns; + else if (cfg.dns4 == NULL) + cfg.dns4 = dns; else { - fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); + fprintf(stderr, "Error: up to 4 DNS servers can be specified\n"); return 1; } } diff --git a/src/firejail/network.c b/src/firejail/network.c index 80f150ea0..5ebaf873c 100644 --- a/src/firejail/network.c +++ b/src/firejail/network.c @@ -28,6 +28,21 @@ #include #include +// return 1 if addr is a IPv4 or IPv6 address +int check_ip46_address(const char *addr) { + // check ipv4 address + uint32_t tmp; + if (atoip(addr, &tmp) == 0) + return 1; + + // check ipv6 address + struct in6_addr result; + if (inet_pton(AF_INET6, addr, &result) == 1) + return 1; + + // failed + return 0; +} int net_get_mtu(const char *ifname) { int mtu = 0; diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 1a944beff..c14f2b1f3 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -668,20 +668,25 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { // dns if (strncmp(ptr, "dns ", 4) == 0) { - uint32_t dns; - if (atoip(ptr + 4, &dns)) { - fprintf(stderr, "Error: invalid DNS server IP address\n"); - return 1; + + if (check_ip46_address(ptr + 4) == 0) { + fprintf(stderr, "Error: invalid DNS server IPv4 or IPv6 address\n"); + exit(1); } + char *dns = strdup(ptr + 4); + if (!dns) + errExit("strdup"); - if (cfg.dns1 == 0) + if (cfg.dns1 == NULL) cfg.dns1 = dns; - else if (cfg.dns2 == 0) + else if (cfg.dns2 == NULL) cfg.dns2 = dns; - else if (cfg.dns3 == 0) + else if (cfg.dns3 == NULL) cfg.dns3 = dns; + else if (cfg.dns4 == NULL) + cfg.dns4 = dns; else { - fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); + fprintf(stderr, "Error: up to 4 DNS servers can be specified\n"); return 1; } return 0; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 010bb06e0..ed0a253b3 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -652,12 +652,14 @@ int sandbox(void* sandbox_arg) { else fmessage("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw)); } - if (cfg.dns1 != 0) - fmessage("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); - if (cfg.dns2 != 0) - fmessage("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); - if (cfg.dns3 != 0) - fmessage("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); + if (cfg.dns1 != NULL) + fmessage("DNS server %s\n", cfg.dns1); + if (cfg.dns2 != NULL) + fmessage("DNS server %s\n", cfg.dns2); + if (cfg.dns3 != NULL) + fmessage("DNS server %s\n", cfg.dns3); + if (cfg.dns4 != NULL) + fmessage("DNS server %s\n", cfg.dns4); fmessage("\n"); } } diff --git a/test/environment/dns.exp b/test/environment/dns.exp index 0d12a82f2..6ddc0ccea 100755 --- a/test/environment/dns.exp +++ b/test/environment/dns.exp @@ -4,7 +4,7 @@ set timeout 30 spawn $env(SHELL) match_max 100000 -send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1\r" +send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1 --dns=::2\r" expect { timeout {puts "TESTING ERROR 2.1\n";exit} "Child process initialized" @@ -24,6 +24,10 @@ expect { timeout {puts "TESTING ERROR 2.4\n";exit} "nameserver 4.2.2.1" } +expect { + timeout {puts "TESTING ERROR 2.5\n";exit} + "nameserver ::2" +} after 100 send -- "exit\r" sleep 1 @@ -50,6 +54,10 @@ expect { "nameserver 4.2.2.1" } after 100 +expect { + timeout {puts "TESTING ERROR 12.5\n";exit} + "nameserver ::2" +} send -- "exit\r" sleep 1 diff --git a/test/environment/dns.profile b/test/environment/dns.profile index d1b842c86..ade2f2650 100644 --- a/test/environment/dns.profile +++ b/test/environment/dns.profile @@ -1,3 +1,4 @@ dns 8.8.4.4 dns 8.8.8.8 dns 4.2.2.1 +dns ::2 diff --git a/test/utils/dns-print.exp b/test/utils/dns-print.exp index 1954844c9..a0fbaa12f 100755 --- a/test/utils/dns-print.exp +++ b/test/utils/dns-print.exp @@ -7,7 +7,7 @@ set timeout 10 spawn $env(SHELL) match_max 100000 -send -- "firejail --name=test --dns=1.2.3.4\r" +send -- "firejail --name=test --dns=1.2.3.4 --dns=::2\r" expect { timeout {puts "TESTING ERROR 0\n";exit} "Child process initialized" @@ -20,5 +20,9 @@ expect { timeout {puts "TESTING ERROR 1\n";exit} "nameserver 1.2.3.4" } +expect { + timeout {puts "TESTING ERROR 1\n";exit} + "nameserver ::2" +} after 100 puts "\nall done\n" -- cgit v1.2.3-54-g00ecf