diff options
Diffstat (limited to 'src/dns/gnunet-helper-dns.c')
-rw-r--r-- | src/dns/gnunet-helper-dns.c | 82 |
1 files changed, 41 insertions, 41 deletions
diff --git a/src/dns/gnunet-helper-dns.c b/src/dns/gnunet-helper-dns.c index bc83da027..8ff6413f8 100644 --- a/src/dns/gnunet-helper-dns.c +++ b/src/dns/gnunet-helper-dns.c | |||
@@ -23,7 +23,7 @@ | |||
23 | * @brief helper to install firewall rules to hijack all DNS traffic | 23 | * @brief helper to install firewall rules to hijack all DNS traffic |
24 | * and send it to our virtual interface (except for DNS traffic | 24 | * and send it to our virtual interface (except for DNS traffic |
25 | * that originates on the specified port). We then | 25 | * that originates on the specified port). We then |
26 | * allow interacting with our virtual interface via stdin/stdout. | 26 | * allow interacting with our virtual interface via stdin/stdout. |
27 | * @author Philipp Tölke | 27 | * @author Philipp Tölke |
28 | * @author Christian Grothoff | 28 | * @author Christian Grothoff |
29 | * | 29 | * |
@@ -55,13 +55,13 @@ | |||
55 | * Naturally, neither of these problems can be helped as this is the | 55 | * Naturally, neither of these problems can be helped as this is the |
56 | * fundamental purpose of the binary. Certifying that this code is | 56 | * fundamental purpose of the binary. Certifying that this code is |
57 | * "safe" thus only means that it doesn't allow anything else (such | 57 | * "safe" thus only means that it doesn't allow anything else (such |
58 | * as local priv. escalation, etc.). | 58 | * as local priv. escalation, etc.). |
59 | * | 59 | * |
60 | * The following list of people have reviewed this code and considered | 60 | * The following list of people have reviewed this code and considered |
61 | * it safe (within specifications) since the last modification (if you | 61 | * it safe (within specifications) since the last modification (if you |
62 | * reviewed it, please have your name added to the list): | 62 | * reviewed it, please have your name added to the list): |
63 | * | 63 | * |
64 | * - Christian Grothoff | 64 | * - Christian Grothoff |
65 | */ | 65 | */ |
66 | #include "platform.h" | 66 | #include "platform.h" |
67 | 67 | ||
@@ -174,7 +174,7 @@ open_dev_null (int target_fd, | |||
174 | if (fd == target_fd) | 174 | if (fd == target_fd) |
175 | return; | 175 | return; |
176 | if (-1 == dup2 (fd, target_fd)) | 176 | if (-1 == dup2 (fd, target_fd)) |
177 | { | 177 | { |
178 | (void) close (fd); | 178 | (void) close (fd); |
179 | abort (); | 179 | abort (); |
180 | } | 180 | } |
@@ -184,13 +184,13 @@ open_dev_null (int target_fd, | |||
184 | 184 | ||
185 | /** | 185 | /** |
186 | * Run the given command and wait for it to complete. | 186 | * Run the given command and wait for it to complete. |
187 | * | 187 | * |
188 | * @param file name of the binary to run | 188 | * @param file name of the binary to run |
189 | * @param cmd command line arguments (as given to 'execv') | 189 | * @param cmd command line arguments (as given to 'execv') |
190 | * @return 0 on success, 1 on any error | 190 | * @return 0 on success, 1 on any error |
191 | */ | 191 | */ |
192 | static int | 192 | static int |
193 | fork_and_exec (const char *file, | 193 | fork_and_exec (const char *file, |
194 | char *const cmd[]) | 194 | char *const cmd[]) |
195 | { | 195 | { |
196 | int status; | 196 | int status; |
@@ -200,8 +200,8 @@ fork_and_exec (const char *file, | |||
200 | pid = fork (); | 200 | pid = fork (); |
201 | if (-1 == pid) | 201 | if (-1 == pid) |
202 | { | 202 | { |
203 | fprintf (stderr, | 203 | fprintf (stderr, |
204 | "fork failed: %s\n", | 204 | "fork failed: %s\n", |
205 | strerror (errno)); | 205 | strerror (errno)); |
206 | return 1; | 206 | return 1; |
207 | } | 207 | } |
@@ -210,25 +210,25 @@ fork_and_exec (const char *file, | |||
210 | /* we are the child process */ | 210 | /* we are the child process */ |
211 | /* close stdin/stdout to not cause interference | 211 | /* close stdin/stdout to not cause interference |
212 | with the helper's main protocol! */ | 212 | with the helper's main protocol! */ |
213 | (void) close (0); | 213 | (void) close (0); |
214 | open_dev_null (0, O_RDONLY); | 214 | open_dev_null (0, O_RDONLY); |
215 | (void) close (1); | 215 | (void) close (1); |
216 | open_dev_null (1, O_WRONLY); | 216 | open_dev_null (1, O_WRONLY); |
217 | (void) execv (file, cmd); | 217 | (void) execv (file, cmd); |
218 | /* can only get here on error */ | 218 | /* can only get here on error */ |
219 | fprintf (stderr, | 219 | fprintf (stderr, |
220 | "exec `%s' failed: %s\n", | 220 | "exec `%s' failed: %s\n", |
221 | file, | 221 | file, |
222 | strerror (errno)); | 222 | strerror (errno)); |
223 | _exit (1); | 223 | _exit (1); |
224 | } | 224 | } |
225 | /* keep running waitpid as long as the only error we get is 'EINTR' */ | 225 | /* keep running waitpid as long as the only error we get is 'EINTR' */ |
226 | while ( (-1 == (ret = waitpid (pid, &status, 0))) && | 226 | while ( (-1 == (ret = waitpid (pid, &status, 0))) && |
227 | (errno == EINTR) ); | 227 | (errno == EINTR) ); |
228 | if (-1 == ret) | 228 | if (-1 == ret) |
229 | { | 229 | { |
230 | fprintf (stderr, | 230 | fprintf (stderr, |
231 | "waitpid failed: %s\n", | 231 | "waitpid failed: %s\n", |
232 | strerror (errno)); | 232 | strerror (errno)); |
233 | return 1; | 233 | return 1; |
234 | } | 234 | } |
@@ -312,8 +312,8 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len) | |||
312 | sa6.sin6_family = AF_INET6; | 312 | sa6.sin6_family = AF_INET6; |
313 | if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) | 313 | if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) |
314 | { | 314 | { |
315 | fprintf (stderr, | 315 | fprintf (stderr, |
316 | "Failed to parse IPv6 address `%s': %s\n", | 316 | "Failed to parse IPv6 address `%s': %s\n", |
317 | address, | 317 | address, |
318 | strerror (errno)); | 318 | strerror (errno)); |
319 | exit (1); | 319 | exit (1); |
@@ -321,11 +321,11 @@ set_address6 (const char *dev, const char *address, unsigned long prefix_len) | |||
321 | 321 | ||
322 | if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) | 322 | if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) |
323 | { | 323 | { |
324 | fprintf (stderr, | 324 | fprintf (stderr, |
325 | "Error creating IPv6 socket: %s (ignored)\n", | 325 | "Error creating IPv6 socket: %s (ignored)\n", |
326 | strerror (errno)); | 326 | strerror (errno)); |
327 | /* ignore error, maybe only IPv4 works on this system! */ | 327 | /* ignore error, maybe only IPv4 works on this system! */ |
328 | return; | 328 | return; |
329 | } | 329 | } |
330 | 330 | ||
331 | memset (&ifr, 0, sizeof (struct ifreq)); | 331 | memset (&ifr, 0, sizeof (struct ifreq)); |
@@ -410,8 +410,8 @@ set_address4 (const char *dev, const char *address, const char *mask) | |||
410 | */ | 410 | */ |
411 | if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr)) | 411 | if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr)) |
412 | { | 412 | { |
413 | fprintf (stderr, | 413 | fprintf (stderr, |
414 | "Failed to parse IPv4 address `%s': %s\n", | 414 | "Failed to parse IPv4 address `%s': %s\n", |
415 | address, | 415 | address, |
416 | strerror (errno)); | 416 | strerror (errno)); |
417 | exit (1); | 417 | exit (1); |
@@ -420,7 +420,7 @@ set_address4 (const char *dev, const char *address, const char *mask) | |||
420 | if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0))) | 420 | if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0))) |
421 | { | 421 | { |
422 | fprintf (stderr, | 422 | fprintf (stderr, |
423 | "Error creating IPv4 socket: %s\n", | 423 | "Error creating IPv4 socket: %s\n", |
424 | strerror (errno)); | 424 | strerror (errno)); |
425 | exit (1); | 425 | exit (1); |
426 | } | 426 | } |
@@ -619,7 +619,7 @@ run (int fd_tun) | |||
619 | return; | 619 | return; |
620 | } | 620 | } |
621 | buftun_size -= written; | 621 | buftun_size -= written; |
622 | buftun_read += written; | 622 | buftun_read += written; |
623 | } | 623 | } |
624 | 624 | ||
625 | if (FD_ISSET (0, &fds_r)) | 625 | if (FD_ISSET (0, &fds_r)) |
@@ -749,7 +749,7 @@ main (int argc, char *const*argv) | |||
749 | return 254; | 749 | return 254; |
750 | } | 750 | } |
751 | #else | 751 | #else |
752 | if (0 != seteuid (0)) | 752 | if (0 != seteuid (0)) |
753 | { | 753 | { |
754 | fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); | 754 | fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); |
755 | return 254; | 755 | return 254; |
@@ -763,7 +763,7 @@ main (int argc, char *const*argv) | |||
763 | sbin_iptables = "/usr/sbin/iptables"; | 763 | sbin_iptables = "/usr/sbin/iptables"; |
764 | else | 764 | else |
765 | { | 765 | { |
766 | fprintf (stderr, | 766 | fprintf (stderr, |
767 | "Fatal: executable iptables not found in approved directories: %s\n", | 767 | "Fatal: executable iptables not found in approved directories: %s\n", |
768 | strerror (errno)); | 768 | strerror (errno)); |
769 | return 3; | 769 | return 3; |
@@ -805,7 +805,7 @@ main (int argc, char *const*argv) | |||
805 | /* setup pipe to shutdown nicely on SIGINT */ | 805 | /* setup pipe to shutdown nicely on SIGINT */ |
806 | if (0 != pipe (cpipe)) | 806 | if (0 != pipe (cpipe)) |
807 | { | 807 | { |
808 | fprintf (stderr, | 808 | fprintf (stderr, |
809 | "Fatal: could not setup control pipe: %s\n", | 809 | "Fatal: could not setup control pipe: %s\n", |
810 | strerror (errno)); | 810 | strerror (errno)); |
811 | return 6; | 811 | return 6; |
@@ -839,14 +839,14 @@ main (int argc, char *const*argv) | |||
839 | } | 839 | } |
840 | if ( (SIG_ERR == signal (SIGTERM, &signal_handler)) || | 840 | if ( (SIG_ERR == signal (SIGTERM, &signal_handler)) || |
841 | (SIG_ERR == signal (SIGINT, &signal_handler)) || | 841 | (SIG_ERR == signal (SIGINT, &signal_handler)) || |
842 | (SIG_ERR == signal (SIGHUP, &signal_handler)) ) | 842 | (SIG_ERR == signal (SIGHUP, &signal_handler)) ) |
843 | { | 843 | { |
844 | fprintf (stderr, | 844 | fprintf (stderr, |
845 | "Fatal: could not initialize signal handler: %s\n", | 845 | "Fatal: could not initialize signal handler: %s\n", |
846 | strerror (errno)); | 846 | strerror (errno)); |
847 | (void) close (cpipe[0]); | 847 | (void) close (cpipe[0]); |
848 | (void) close (cpipe[1]); | 848 | (void) close (cpipe[1]); |
849 | return 7; | 849 | return 7; |
850 | } | 850 | } |
851 | 851 | ||
852 | 852 | ||
@@ -868,8 +868,8 @@ main (int argc, char *const*argv) | |||
868 | return 5; | 868 | return 5; |
869 | } | 869 | } |
870 | } | 870 | } |
871 | 871 | ||
872 | 872 | ||
873 | /* now open virtual interface (first part that requires root) */ | 873 | /* now open virtual interface (first part that requires root) */ |
874 | if (-1 == (fd_tun = init_tun (dev))) | 874 | if (-1 == (fd_tun = init_tun (dev))) |
875 | { | 875 | { |
@@ -907,14 +907,14 @@ main (int argc, char *const*argv) | |||
907 | set_address4 (dev, address, mask); | 907 | set_address4 (dev, address, mask); |
908 | } | 908 | } |
909 | 909 | ||
910 | 910 | ||
911 | /* update routing tables -- next part why we need SUID! */ | 911 | /* update routing tables -- next part why we need SUID! */ |
912 | /* Forward everything from our EGID (which should only be held | 912 | /* Forward everything from our EGID (which should only be held |
913 | by the 'gnunet-service-dns') and with destination | 913 | by the 'gnunet-service-dns') and with destination |
914 | to port 53 on UDP, without hijacking */ | 914 | to port 53 on UDP, without hijacking */ |
915 | r = 8; /* failed to fully setup routing table */ | 915 | r = 8; /* failed to fully setup routing table */ |
916 | { | 916 | { |
917 | char *const mangle_args[] = | 917 | char *const mangle_args[] = |
918 | { | 918 | { |
919 | "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", | 919 | "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", |
920 | "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", | 920 | "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", |
@@ -922,7 +922,7 @@ main (int argc, char *const*argv) | |||
922 | }; | 922 | }; |
923 | if (0 != fork_and_exec (sbin_iptables, mangle_args)) | 923 | if (0 != fork_and_exec (sbin_iptables, mangle_args)) |
924 | goto cleanup_rest; | 924 | goto cleanup_rest; |
925 | } | 925 | } |
926 | /* Mark all of the other DNS traffic using our mark DNS_MARK */ | 926 | /* Mark all of the other DNS traffic using our mark DNS_MARK */ |
927 | { | 927 | { |
928 | char *const mark_args[] = | 928 | char *const mark_args[] = |
@@ -965,7 +965,7 @@ main (int argc, char *const*argv) | |||
965 | } | 965 | } |
966 | #else | 966 | #else |
967 | /* Note: no 'setuid' here as we must keep our saved UID as root */ | 967 | /* Note: no 'setuid' here as we must keep our saved UID as root */ |
968 | if (0 != seteuid (uid)) | 968 | if (0 != seteuid (uid)) |
969 | { | 969 | { |
970 | fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno)); | 970 | fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno)); |
971 | r = 24; | 971 | r = 24; |
@@ -977,7 +977,7 @@ main (int argc, char *const*argv) | |||
977 | 977 | ||
978 | /* now forward until we hit a problem */ | 978 | /* now forward until we hit a problem */ |
979 | run (fd_tun); | 979 | run (fd_tun); |
980 | 980 | ||
981 | /* now need to regain privs so we can remove the firewall rules we added! */ | 981 | /* now need to regain privs so we can remove the firewall rules we added! */ |
982 | #ifdef HAVE_SETRESUID | 982 | #ifdef HAVE_SETRESUID |
983 | if (0 != setresuid (uid, 0, 0)) | 983 | if (0 != setresuid (uid, 0, 0)) |
@@ -987,19 +987,19 @@ main (int argc, char *const*argv) | |||
987 | goto cleanup_route_4; | 987 | goto cleanup_route_4; |
988 | } | 988 | } |
989 | #else | 989 | #else |
990 | if (0 != seteuid (0)) | 990 | if (0 != seteuid (0)) |
991 | { | 991 | { |
992 | fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); | 992 | fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); |
993 | r = 40; | 993 | r = 40; |
994 | goto cleanup_route_4; | 994 | goto cleanup_route_4; |
995 | } | 995 | } |
996 | #endif | 996 | #endif |
997 | 997 | ||
998 | /* update routing tables again -- this is why we could not fully drop privs */ | 998 | /* update routing tables again -- this is why we could not fully drop privs */ |
999 | /* now undo updating of routing tables; normal exit or clean-up-on-error case */ | 999 | /* now undo updating of routing tables; normal exit or clean-up-on-error case */ |
1000 | cleanup_route_4: | 1000 | cleanup_route_4: |
1001 | { | 1001 | { |
1002 | char *const route_clean_args[] = | 1002 | char *const route_clean_args[] = |
1003 | { | 1003 | { |
1004 | "ip", "route", "del", "default", "dev", dev, | 1004 | "ip", "route", "del", "default", "dev", dev, |
1005 | "table", DNS_TABLE, NULL | 1005 | "table", DNS_TABLE, NULL |