int execute_cmd(char *cmd, int in) { char *p = cmd; char *start_cmd = cmd; int pipefd[2]; while (*p) { switch (*p) { case '|': *p++ = 0; //创建一个管道 pipe(pipefd); //下面的语句执行后,程序分叉,第一叉在当前捕获的命令,第二 //叉在后面继续解析命令 //将写管道传给当前捕获的命令用于重定向其stdout if (fork_and_exec(start_cmd, in, pipefd[1]) > 0) { //将读管道传给将要被捕获的命令用于重定向其stdin goto call_forward_pipe_chain; } break; default: p++; } } fork_and_exec(start_cmd, in, -1); fflush(stdout); return 0; call_forward_pipe_chain: execute_cmd(p, pipefd[0]); fflush(stdout); return 0; }
static void do_help (saver_screen_info *ssi) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; char *help_command = 0; if (!p->load_url_command || !*p->load_url_command) { fprintf (stderr, "%s: no URL command has been specified.\n", blurb()); return; } if (!p->help_url || !*p->help_url) { fprintf (stderr, "%s: no Help URL has been specified.\n", blurb()); return; } help_command = (char *) malloc (strlen (p->load_url_command) + (strlen (p->help_url) * 4) + 10); sprintf (help_command, p->load_url_command, p->help_url, p->help_url, p->help_url, p->help_url); fork_and_exec (ssi, help_command); free (help_command); }
void VMError::show_message_box(char *buf, int buflen) { bool yes; do { error_string(buf, buflen); int len = (int)strlen(buf); char *p = &buf[len]; jio_snprintf(p, buflen - len, "\n\n" "Do you want to debug the problem?\n\n" "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT "\n" "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n" "Otherwise, press RETURN to abort...", os::current_process_id(), os::current_process_id(), os::current_thread_id()); yes = os::message_box("Unexpected Error", buf); if (yes) { // yes, user asked VM to launch debugger jio_snprintf(buf, buflen, "gdb /proc/%d/exe %d", os::current_process_id(), os::current_process_id()); fork_and_exec(buf); } } while (yes); }
static void do_prefs (saver_screen_info *ssi) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; const char *cmd = p->prefs_command; if (command && *command) fork_and_exec (ssi, cmd); else fprintf (stderr, "%s: no preferences command has been specified.\n", blurb()); }
int do_pipes(t_dlist *list, char ***env) { t_pipes var; init_function_pipe(&var); while (var.i < list->taille) { if (list->begin->s != NULL && list->begin->s[0] == '<') { list->begin = list->begin->next; if ((var.fd_in = redirection_left(list, &var.i, &var.j)) == -1) return (0); } if (do_next_command(list->begin, list->end, &var) == -1) return (0); if (var.j == 0) fork_and_exec(list->begin, env, var.fd_in, var.fd_out); else var.j = fork_and_exec(list->begin->prev, env, var.fd_in, var.fd_out); close_function_pipe(&var); list->begin = list->begin->next; } return (0); }
int main() { char cmdline[1024]; char *args[64]; char * pathArgs[64]; char fullcmd [100]; int i; printf("%s","This is a Simple Shell \n"); while(1) { i = 0; print_prompt(); // printf("%s", "test 1"); read_command(cmdline); // printf("%s", "test 2"); // printf("After read_command %s \n", buf); parse_command(cmdline, args); // printf("%s", "test 3"); // printf("After parse_command %s \n", buf); // printf("After parse_comamnd %s \n", args); // printf("More curiosity \n"); file_find(pathArgs, cmdline, fullcmd); // while (pathArgs[i] != NULL){ // strcat(pathArgs[i], "/"); // //printf("args [i] is: %s/ls\n", pathArgs[i]); // i++; // } // printf("After file_find %s \n", args); // printf("%s", "test 4"); // printf("%s", *args); fork_and_exec(args, fullcmd); //printf("After fork %s", buf); //printf("%s", "test 5 \n"); return 0; } }
int main (int argc, char *const *argv) { char *sbin_iptables; char *bin_vpn; char *bin_exit; char *bin_dns; char *srv_dns; struct stat s; gid_t my_gid; char *const iptables_args[] = { "iptables", "-t", "mangle", "-L", "-v", NULL }; if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Executable iptables not found in approved directories: %s, skipping\n", strerror (errno)); return 0; } if (0 != fork_and_exec (sbin_iptables, iptables_args)) { fprintf (stderr, "Failed to run `iptables -t mangle -L -v'. Skipping test.\n"); return 0; } if (0 != ACCESS ("/dev/net/tun", R_OK)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "access", "/dev/net/tun"); fprintf (stderr, "WARNING: System unable to run test, skipping.\n"); return 0; } bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); bin_dns = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns"); srv_dns = GNUNET_OS_get_libexec_binary_path ("gnunet-service-dns"); if ( (0 != geteuid ()) && ( (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_vpn, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) || //ipv4 only please! (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_exit, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) || //no nat, ipv4 only (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_dns, GNUNET_YES, NULL))) ) // TODO: once we have a windows-testcase, add test parameters here { fprintf (stderr, "WARNING: gnunet-helper-{exit,vpn,dns} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n"); fprintf (stderr, "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n"); GNUNET_free (bin_vpn); GNUNET_free (bin_exit); GNUNET_free (bin_dns); GNUNET_free (srv_dns); return 0; } GNUNET_free (bin_vpn); GNUNET_free (bin_exit); my_gid = getgid (); if ( (0 != stat (bin_dns, &s)) || (my_gid == s.st_gid) || ( (0 == (S_ISUID & s.st_mode)) && (0 != getuid()) ) ) { fprintf (stderr, "WARNING: %s has wrong permissions (%d, %d, %d), refusing to run test (as it would have to fail).\n", bin_dns, (0 != stat (bin_dns, &s)), (my_gid == s.st_gid), (0 == (S_ISUID & s.st_mode)) || (0 != getuid()) ); GNUNET_free (bin_dns); GNUNET_free (srv_dns); return 0; } if ( (0 != stat (srv_dns, &s)) || (my_gid == s.st_gid) || (0 == (S_ISGID & s.st_mode)) ) { fprintf (stderr, "WARNING: %s has wrong permissions (%d, %d, %d), refusing to run test (as it would have to fail).\n", srv_dns, (0 != stat (bin_dns, &s)), (my_gid == s.st_gid), (0 == (S_ISGID & s.st_mode)) ); GNUNET_free (bin_dns); GNUNET_free (srv_dns); return 0; } GNUNET_free (bin_dns); GNUNET_free (srv_dns); dest_ip = "169.254.86.1"; dest_af = AF_INET; src_af = AF_INET; if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6)) use_v6 = GNUNET_YES; else use_v6 = GNUNET_NO; if ( (GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) || (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af)) ) { fprintf (stderr, "Required address families not supported by this system, skipping test.\n"); return 0; } if (0 != curl_global_init (CURL_GLOBAL_WIN32)) { fprintf (stderr, "failed to initialize curl\n"); return 2; } if (0 != GNUNET_TESTING_peer_run ("test-gnunet-vpn", "test_gns_vpn.conf", &run, NULL)) return 1; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); return global_ret; }
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { enum MHD_FLAG flags; char *bin; char *bin_identity; char *bin_gns; char *config; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "CONFIG", &config)) { fprintf (stderr, "Failed to locate configuration file. Skipping test.\n"); GNUNET_SCHEDULER_shutdown (); return; } char *const identity_args[] = { "gnunet-identity", "-C", "master-zone", "-c", config, NULL }; char *const identity2_args[] = { "gnunet-identity", "-e", "master-zone", "-s", "gns-master", "-c", config, NULL }; char *const identity3_args[] = { "gnunet-identity", "-e", "master-zone", "-s", "gns-intercept", "-c", config, NULL }; char *const gns_args[] = { "gnunet-gns", "-u", "www.gns", "-c", config, NULL }; GNUNET_TESTING_peer_get_identity (peer, &id); GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shutdown, NULL); bin = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); GNUNET_asprintf (&bin_identity, "%s/%s", bin, "gnunet-identity"); if (0 != fork_and_exec (bin_identity, identity_args)) { fprintf (stderr, "Failed to run `gnunet-identity -C. Skipping test.\n"); GNUNET_SCHEDULER_shutdown (); GNUNET_free (bin_identity); GNUNET_free (config); GNUNET_free (bin); return; } if (0 != fork_and_exec (bin_identity, identity2_args)) { fprintf (stderr, "Failed to run `gnunet-identity -e. Skipping test.\n"); GNUNET_SCHEDULER_shutdown (); GNUNET_free (bin_identity); GNUNET_free (config); GNUNET_free (bin); return; } if (0 != fork_and_exec (bin_identity, identity3_args)) { fprintf (stderr, "Failed to run `gnunet-identity -e. Skipping test.\n"); GNUNET_SCHEDULER_shutdown (); GNUNET_free (bin_identity); GNUNET_free (config); GNUNET_free (bin); return; } GNUNET_free (bin_identity); /* do lookup just to launch GNS service */ GNUNET_asprintf (&bin_gns, "%s/%s", bin, "gnunet-gns"); if (0 != fork_and_exec (bin_gns, gns_args)) { fprintf (stderr, "Failed to run `gnunet-gns -u. Skipping test.\n"); GNUNET_SCHEDULER_shutdown (); GNUNET_free (bin_gns); GNUNET_free (config); GNUNET_free (bin); return; } GNUNET_free (bin_gns); GNUNET_free (config); GNUNET_free (bin); namestore = GNUNET_NAMESTORE_connect (cfg); GNUNET_assert (NULL != namestore); flags = MHD_USE_DEBUG; if (GNUNET_YES == use_v6) flags |= MHD_USE_DUAL_STACK; mhd = MHD_start_daemon (flags, PORT, NULL, NULL, &mhd_ahc, NULL, MHD_OPTION_END); GNUNET_assert (NULL != mhd); mhd_main (); identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); }
/** * Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, * redirects all outgoing DNS traffic (except from the specified port) to that * interface and then passes traffic from and to the interface via stdin/stdout. * * Once stdin/stdout close or have other errors, the tunnel is closed and the * DNS traffic redirection is stopped. * * @param argc number of arguments * @param argv 0: binary name (should be "gnunet-helper-vpn") * 1: tunnel interface name (typically "gnunet-dns") * 2: IPv6 address for the tunnel ("FE80::1") * 3: IPv6 netmask length in bits ("64") * 4: IPv4 address for the tunnel ("1.2.3.4") * 5: IPv4 netmask ("255.255.0.0") * 6: skip sysctl, routing and iptables setup ("0") * @return 0 on success, otherwise code indicating type of error: * 1 wrong number of arguments * 2 invalid arguments (i.e. port number / prefix length wrong) * 3 iptables not executable * 4 ip not executable * 5 failed to initialize tunnel interface * 6 failed to initialize control pipe * 8 failed to change routing table, cleanup successful * 9-23 failed to change routing table and failed to undo some changes to routing table * 24 failed to drop privs * 25-39 failed to drop privs and then failed to undo some changes to routing table * 40 failed to regain privs * 41-55 failed to regain prisv and then failed to undo some changes to routing table * 254 insufficient priviledges * 255 failed to handle kill signal properly */ int main (int argc, char *const*argv) { int r; char dev[IFNAMSIZ]; char mygid[32]; int fd_tun; uid_t uid; int nortsetup = 0; if (7 != argc) { fprintf (stderr, "Fatal: must supply 6 arguments!\n"); return 1; } /* assert privs so we can modify the firewall rules! */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); return 254; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); return 254; } #endif if (0 == strncmp (argv[6], "1", 2)) nortsetup = 1; if (0 == nortsetup) { /* verify that the binaries we care about are executable */ if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Fatal: executable iptables not found in approved directories: %s\n", strerror (errno)); return 3; } if (0 == access ("/sbin/ip6tables", X_OK)) sbin_ip6tables = "/sbin/ip6tables"; else if (0 == access ("/usr/sbin/ip6tables", X_OK)) sbin_ip6tables = "/usr/sbin/ip6tables"; else { fprintf (stderr, "Fatal: executable ip6tables not found in approved directories: %s\n", strerror (errno)); return 3; } if (0 == access ("/sbin/ip", X_OK)) sbin_ip = "/sbin/ip"; else if (0 == access ("/usr/sbin/ip", X_OK)) sbin_ip = "/usr/sbin/ip"; else { fprintf (stderr, "Fatal: executable ip not found in approved directories: %s\n", strerror (errno)); return 4; } if (0 == access ("/sbin/sysctl", X_OK)) sbin_sysctl = "/sbin/sysctl"; else if (0 == access ("/usr/sbin/sysctl", X_OK)) sbin_sysctl = "/usr/sbin/sysctl"; else { fprintf (stderr, "Fatal: executable sysctl not found in approved directories: %s\n", strerror (errno)); return 5; } } /* setup 'mygid' string */ snprintf (mygid, sizeof (mygid), "%d", (int) getegid()); /* do not die on SIGPIPE */ if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); return 7; } /* setup pipe to shutdown nicely on SIGINT */ if (0 != pipe (cpipe)) { fprintf (stderr, "Fatal: could not setup control pipe: %s\n", strerror (errno)); return 6; } if (cpipe[0] >= FD_SETSIZE) { fprintf (stderr, "Pipe file descriptor to large: %d", cpipe[0]); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } { /* make pipe non-blocking, as we theoretically could otherwise block in the signal handler */ int flags = fcntl (cpipe[1], F_GETFL); if (-1 == flags) { fprintf (stderr, "Failed to read flags for pipe: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } flags |= O_NONBLOCK; if (0 != fcntl (cpipe[1], F_SETFL, flags)) { fprintf (stderr, "Failed to make pipe non-blocking: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } } if ( (SIG_ERR == signal (SIGTERM, &signal_handler)) || #if (SIGTERM != GNUNET_TERM_SIG) (SIG_ERR == signal (GNUNET_TERM_SIG, &signal_handler)) || #endif (SIG_ERR == signal (SIGINT, &signal_handler)) || (SIG_ERR == signal (SIGHUP, &signal_handler)) ) { fprintf (stderr, "Fatal: could not initialize signal handler: %s\n", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 7; } /* get interface name */ strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; /* Disable rp filtering */ if (0 == nortsetup) { char *const sysctl_args[] = {"sysctl", "-w", "net.ipv4.conf.all.rp_filter=0", NULL}; char *const sysctl_args2[] = {"sysctl", "-w", "net.ipv4.conf.default.rp_filter=0", NULL}; if ((0 != fork_and_exec (sbin_sysctl, sysctl_args)) || (0 != fork_and_exec (sbin_sysctl, sysctl_args2))) { fprintf (stderr, "Failed to disable rp filtering.\n"); return 5; } } /* now open virtual interface (first part that requires root) */ if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface\n"); (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 5; } /* now set interface addresses */ { const char *address = argv[2]; long prefix_len = atol (argv[3]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 2; } set_address6 (dev, address, prefix_len); } { const char *address = argv[4]; const char *mask = argv[5]; set_address4 (dev, address, mask); } /* update routing tables -- next part why we need SUID! */ /* Forward everything from our EGID (which should only be held by the 'gnunet-service-dns') and with destination to port 53 on UDP, without hijacking */ if (0 == nortsetup) { r = 8; /* failed to fully setup routing table */ { char *const mangle_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_args)) goto cleanup_rest; } { char *const mangle_args[] = { "ip6tables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_ip6tables, mangle_args)) goto cleanup_mangle_1b; } /* Mark all of the other DNS traffic using our mark DNS_MARK, unless it is on a link-local IPv6 address, which we cannot support. */ { char *const mark_args[] = { "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_args)) goto cleanup_mangle_1; } { char *const mark_args[] = { "ip6tables", "-t", "mangle", "-I", "OUTPUT", "2", "-p", "udp", "--dport", DNS_PORT, "!", "-s", "fe80::/10", /* this line excludes link-local traffic */ "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_ip6tables, mark_args)) goto cleanup_mark_2b; } /* Forward all marked DNS traffic to our DNS_TABLE */ { char *const forward_args[] = { "ip", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_args)) goto cleanup_mark_2; } { char *const forward_args[] = { "ip", "-6", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_args)) goto cleanup_forward_3b; } /* Finally, add rule in our forwarding table to pass to our virtual interface */ { char *const route_args[] = { "ip", "route", "add", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_args)) goto cleanup_forward_3; } { char *const route_args[] = { "ip", "-6", "route", "add", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_args)) goto cleanup_route_4b; } } /* drop privs *except* for the saved UID; this is not perfect, but better than doing nothing */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, 0)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #else /* Note: no 'setuid' here as we must keep our saved UID as root */ if (0 != seteuid (uid)) { fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #endif r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */ /* now forward until we hit a problem */ run (fd_tun); /* now need to regain privs so we can remove the firewall rules we added! */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #endif /* update routing tables again -- this is why we could not fully drop privs */ /* now undo updating of routing tables; normal exit or clean-up-on-error case */ cleanup_route_4: if (0 == nortsetup) { char *const route_clean_args[] = { "ip", "-6", "route", "del", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_clean_args)) r += 1; } cleanup_route_4b: if (0 == nortsetup) { char *const route_clean_args[] = { "ip", "route", "del", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_clean_args)) r += 1; } cleanup_forward_3: if (0 == nortsetup) { char *const forward_clean_args[] = { "ip", "-6", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_clean_args)) r += 2; } cleanup_forward_3b: if (0 == nortsetup) { char *const forward_clean_args[] = { "ip", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_clean_args)) r += 2; } cleanup_mark_2: if (0 == nortsetup) { char *const mark_clean_args[] = { "ip6tables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--dport", DNS_PORT, "!", "-s", "fe80::/10", /* this line excludes link-local traffic */ "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_ip6tables, mark_clean_args)) r += 4; } cleanup_mark_2b: if (0 == nortsetup) { char *const mark_clean_args[] = { "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_clean_args)) r += 4; } cleanup_mangle_1: if (0 == nortsetup) { char *const mangle_clean_args[] = { "ip6tables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_ip6tables, mangle_clean_args)) r += 8; } cleanup_mangle_1b: if (0 == nortsetup) { char *const mangle_clean_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_clean_args)) r += 8; } cleanup_rest: /* close virtual interface */ (void) close (fd_tun); /* remove signal handler so we can close the pipes */ (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return r; }
/** * Open VPN tunnel interface. * * @param argc must be 6 * @param argv 0: binary name ("gnunet-helper-exit") * 1: tunnel interface name ("gnunet-exit") * 2: IPv4 "physical" interface name ("eth0"), or "%" to not do IPv4 NAT * 3: IPv6 address ("::1"), or "-" to skip IPv6 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"] * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"] */ int main (int argc, char **argv) { char dev[IFNAMSIZ]; int fd_tun; int global_ret; if (7 != argc) { fprintf (stderr, "Fatal: must supply 6 arguments!\n"); return 1; } if ( (0 == strcmp (argv[3], "-")) && (0 == strcmp (argv[5], "-")) ) { fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n"); return 1; } if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Fatal: executable iptables not found in approved directories: %s\n", strerror (errno)); return 1; } if (0 == access ("/sbin/sysctl", X_OK)) sbin_sysctl = "/sbin/sysctl"; else if (0 == access ("/usr/sbin/sysctl", X_OK)) sbin_sysctl = "/usr/sbin/sysctl"; else { fprintf (stderr, "Fatal: executable sysctl not found in approved directories: %s\n", strerror (errno)); return 1; } strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n", dev, argv[3], argv[4], argv[5], argv[6]); return 1; } if (0 != strcmp (argv[3], "-")) { { const char *address = argv[3]; long prefix_len = atol (argv[4]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); return 1; } set_address6 (dev, address, prefix_len); } { char *const sysctl_args[] = { "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL }; if (0 != fork_and_exec (sbin_sysctl, sysctl_args)) { fprintf (stderr, "Failed to enable IPv6 forwarding. Will continue anyway.\n"); } } } if (0 != strcmp (argv[5], "-")) { { const char *address = argv[5]; const char *mask = argv[6]; set_address4 (dev, address, mask); } { char *const sysctl_args[] = { "sysctl", "-w", "net.ipv4.ip_forward=1", NULL }; if (0 != fork_and_exec (sbin_sysctl, sysctl_args)) { fprintf (stderr, "Failed to enable IPv4 forwarding. Will continue anyway.\n"); } } if (0 != strcmp (argv[2], "%")) { char *const iptables_args[] = { "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL }; if (0 != fork_and_exec (sbin_iptables, iptables_args)) { fprintf (stderr, "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n"); } } } uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #endif if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); /* no exit, we might as well die with SIGPIPE should it ever happen */ } run (fd_tun); global_ret = 0; cleanup: (void) close (fd_tun); return global_ret; }