static void natvDumpRulesHelper( PLIST_ENTRY pRuleHead, NDIS_SPIN_LOCK *pRuleLock ) { FLT_RULE *pRule; PLIST_ENTRY pRuleEntry; char pubIpAddrStr[30]; char prvIpAddrStr[30]; char pubMaskStr[30]; char prvMaskStr[30]; NdisAcquireSpinLock(pRuleLock); for(pRuleEntry = pRuleHead->Flink; pRuleEntry != pRuleHead; pRuleEntry = pRuleEntry->Flink ){ pRule = CONTAINING_RECORD(pRuleEntry, FLT_RULE, ListEntry); PRINT_IP(pubIpAddrStr, &pRule->pubAddr); PRINT_IP(pubMaskStr, &pRule->pubMask); PRINT_IP(prvIpAddrStr, &pRule->prvAddr); PRINT_IP(prvMaskStr, &pRule->prvMask); DbgPrint("%s RULE: ALLOW PUB=%s/%s PRV=%s/%s DST PORT=%u\n", pRule->out ? "OUTGOING" : "INCOMING", pubIpAddrStr,pubMaskStr, prvIpAddrStr,prvMaskStr, RtlUshortByteSwap(pRule->port)); } NdisReleaseSpinLock(pRuleLock); }
// configure bridge structure // - extract ip address and mask from the bridge interface void net_configure_bridge(Bridge *br, char *dev_name) { assert(br); assert(dev_name); br->dev = dev_name; // check the bridge device exists char sysbridge[30 + strlen(br->dev)]; sprintf(sysbridge, "/sys/class/net/%s/bridge", br->dev); struct stat s; int rv = stat(sysbridge, &s); if (rv == 0) { // this is a bridge device br->macvlan = 0; } else { // is this a regular Ethernet interface if (if_nametoindex(br->dev) > 0) { br->macvlan = 1; char *newname; if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1) errExit("asprintf"); br->devsandbox = newname; } else { fprintf(stderr, "Error: cannot find network device %s\n", br->dev); exit(1); } } // allow unconfigured interfaces if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac, &br->mtu)) { fprintf(stderr, "Warning: the network interface %s is not configured\n", br->dev); br->configured = 1; br->arg_ip_none = 1; return; } if (arg_debug) { if (br->macvlan == 0) printf("Bridge device %s at %d.%d.%d.%d/%d\n", br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); else printf("macvlan parent device %s at %d.%d.%d.%d/%d\n", br->dev, PRINT_IP(br->ip), mask2bits(br->mask)); } uint32_t range = ~br->mask + 1; // the number of potential addresses // this software is not supported for /31 networks if (range < 4) { fprintf(stderr, "Error: the software is not supported for /31 networks\n"); exit(1); } br->configured = 1; }
static void print_arp(const char *fname) { FILE *fp = fopen(fname, "r"); if (!fp) return; printf(" ARP Table:\n"); char buf[MAXBUF]; while (fgets(buf, MAXBUF, fp)) { // remove blanks, \n char *ptr = buf; while (*ptr == ' ' || *ptr == '\t') ptr++; char *start = ptr; if (*start == '\0') continue; ptr = strchr(ptr, '\n'); if (ptr) *ptr = '\0'; // remove table header //IP address HW type Flags HW address Mask Device if (strncmp(start, "IP address", 10) == 0) continue; // extract data char ip[64]; char type[64]; char flags[64]; char mac[64]; char mask[64]; char device[64]; int rv = sscanf(start, "%s %s %s %s %s %s\n", ip, type, flags, mac, mask, device); if (rv != 6) continue; // destination ip unsigned a, b, c, d; if (sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d) != 4 || a > 255 || b > 255 || c > 255 || d > 255) continue; uint32_t destip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d; if (strcmp(flags, "0x0") == 0) printf(" %d.%d.%d.%d dev %s FAILED\n", PRINT_IP(destip), device); else printf(" %d.%d.%d.%d dev %s lladdr %s REACHABLE\n", PRINT_IP(destip), device, mac); } fclose(fp); }
// assign a random IP address and check it // the address needs to be in the range if it --iprange was specified static uint32_t arp_random(const char *dev, Bridge *br) { assert(dev); assert(br); uint32_t ifip = br->ip; uint32_t ifmask = br->mask; assert(ifip); assert(ifmask); if (arg_debug) printf("ARP-scan %s, %d.%d.%d.%d/%d\n", dev, PRINT_IP(ifip), mask2bits(ifmask)); // determine the range based on network address uint32_t range = ~ifmask + 1; // the number of potential addresses // this software is not supported for /31 networks if (range < 4) return 0; // the user will have to set the IP address manually range -= 2; // subtract the network address and the broadcast address uint32_t start = (ifip & ifmask) + 1; // adjust range based on --iprange params if (br->iprange_start && br->iprange_end) { start = br->iprange_start; range = br->iprange_end - br->iprange_start; } if (arg_debug) printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n", PRINT_IP(start), PRINT_IP(start + range)); // generate a random address - 10 tries uint32_t dest = 0; int i = 0; for (i = 0; i < 10; i++) { dest = start + ((uint32_t) rand()) % range; if (dest == ifip) // do not allow the interface address continue; // try again // if we've made it up to here, we have a valid address break; } if (i == 10) // we failed 10 times return 0; // check address uint32_t rv = arp_check(dev, dest, ifip); if (!rv) return dest; return 0; }
static void sandbox_if_up(Bridge *br) { assert(br); if (!br->configured) return; char *dev = br->devsandbox; net_if_up(dev); if (br->arg_ip_none == 1); // do nothing else if (br->arg_ip_none == 0 && br->macvlan == 0) { if (br->ipsandbox == br->ip) { fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); exit(1); } // just assign the address assert(br->ipsandbox); if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); net_if_up(dev); } else if (br->arg_ip_none == 0 && br->macvlan == 1) { // reassign the macvlan address if (br->ipsandbox == 0) // ip address assigned by arp-scan for a macvlan device br->ipsandbox = arp_assign(dev, br); //br->ip, br->mask); else { if (br->ipsandbox == br->ip) { fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev); exit(1); } uint32_t rv = arp_check(dev, br->ipsandbox, br->ip); if (rv) { fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox)); exit(1); } } if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); net_if_up(dev); } if (br->ip6sandbox) net_if_ip6(dev, br->ip6sandbox); }
void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) { assert(br); if (br->configured == 0) return; // create a veth pair char *dev; if (br->veth_name == NULL) { if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0) errExit("asprintf"); } else dev = br->veth_name; char *cstr; if (asprintf(&cstr, "%d", child) == -1) errExit("asprintf"); sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7, PATH_FNET, "create", "veth", dev, ifname, br->dev, cstr); free(cstr); char *msg; if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1) errExit("asprintf"); logmsg(msg); fflush(0); free(msg); }
static void print_ip(kssl_operation *op, char *ip_string) { if (op == NULL) return; if (op->is_ip_set) { // IPv4 printing if (op->ip_len == 4) { struct in_addr ip; memcpy((void *)&ip.s_addr, op->ip, 4); PRINT_IP(AF_INET, &ip, ip_string, INET_ADDRSTRLEN); } if (op->ip_len == 16) { struct in6_addr ip; memcpy((void *)ip.s6_addr, op->ip, 16); PRINT_IP(AF_INET6, &ip, ip_string, INET6_ADDRSTRLEN); } } }
// go sequentially trough all IP addresses and assign the first one not in use static uint32_t arp_sequential(const char *dev, Bridge *br) { assert(dev); assert(br); uint32_t ifip = br->ip; uint32_t ifmask = br->mask; assert(ifip); assert(ifmask); // range based on network address uint32_t range = ~ifmask + 1; // the number of potential addresses // this software is not supported for /31 networks if (range < 4) return 0; // the user will have to set the IP address manually range -= 2; // subtract the network address and the broadcast address // try all possible ip addresses in ascending order // start address uint32_t dest = (ifip & ifmask) + 1; if (br->iprange_start) dest = br->iprange_start; // end address uint32_t last = dest + range - 1; if (br->iprange_end) last = br->iprange_end; if (arg_debug) printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n", PRINT_IP(dest), PRINT_IP(last)); // loop through addresses and stop as soon as you find an unused one while (dest <= last) { if (dest == ifip) { dest++; continue; } uint32_t rv = arp_check(dev, dest, ifip); if (!rv) return dest; dest++; } return 0; }
/*print port and addresses based on sock*/ void ant_debug_sock(int sock) { struct sockaddr_in addr; int olderrno; socklen_t len = sizeof(addr); olderrno = errno; memset(&addr, '\0', sizeof(addr)); if (getpeername(sock, (struct sockaddr*)&addr, &len) < 0) { errno = olderrno; } PRINT_IP(addr.sin_addr.s_addr); fprintf(stderr, "port = %hd\n", ntohs(addr.sin_port)); }
void fs_resolvconf(void) { if (cfg.dns1 == 0) return; struct stat s; // create a new /etc/hostname if (stat("/etc/resolv.conf", &s) == 0) { if (arg_debug) printf("Creating a new /etc/resolv.conf file\n"); FILE *fp = fopen(RUN_RESOLVCONF_FILE, "w"); if (!fp) { fprintf(stderr, "Error: cannot create %s\n", RUN_RESOLVCONF_FILE); exit(1); } if (cfg.dns1) fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); if (cfg.dns2) fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); if (cfg.dns3) fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); // mode and owner SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); fclose(fp); // bind-mount the file on top of /etc/hostname if (mount(RUN_RESOLVCONF_FILE, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind /etc/resolv.conf"); fs_logger("create /etc/resolv.conf"); } else { fprintf(stderr, "Error: cannot set DNS servers, /etc/resolv.conf file is missing\n"); exit(1); } }
void net_check_cfg(void) { int net_configured = 0; if (cfg.bridge0.configured) net_configured++; if (cfg.bridge1.configured) net_configured++; if (cfg.bridge2.configured) net_configured++; if (cfg.bridge3.configured) net_configured++; // --defaultgw requires a network if (cfg.defaultgw && net_configured == 0) { fprintf(stderr, "Error: option --defaultgw requires at least one network to be configured\n"); exit(1); } if (net_configured == 0) // nothing to check return; // --net=none if (arg_nonetwork && net_configured) { fprintf(stderr, "Error: --net and --net=none are mutually exclusive\n"); exit(1); } // check default gateway address or assign one assert(cfg.bridge0.configured); if (cfg.defaultgw) check_default_gw(cfg.defaultgw); else { // first network is a regular bridge if (cfg.bridge0.macvlan == 0) cfg.defaultgw = cfg.bridge0.ip; // first network is a mac device else { // get the host default gw uint32_t gw = network_get_defaultgw(); // check the gateway is network range if (in_netrange(gw, cfg.bridge0.ip, cfg.bridge0.mask)) gw = 0; cfg.defaultgw = gw; } if (cfg.defaultgw == 0) fprintf(stderr, "Warning: default network gateway not set.\n"); else fprintf(stderr, "Using %d.%d.%d.%d as default gateway.\n", PRINT_IP(cfg.defaultgw)); } }
void natvLogSession( IN const char * prefixStr, IN TRACED_CONNECTION* pItem, IN ULONG prevState, IN const char * sufixStr ) { TIME_FIELDS TimeFields; char timeStr[30]; LARGE_INTEGER time; char dstIpAddrStr[30]; char srcIpAddrStr[30]; KeQuerySystemTime(&time); ExSystemTimeToLocalTime(&time, &time); RtlTimeToTimeFields(&time, &TimeFields); RtlStringCbPrintfA(timeStr, sizeof(timeStr), "%02d:%02d:%02d.%03d ", TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds); PRINT_IP(dstIpAddrStr, &pItem->dstIpAddrOrg); PRINT_IP(srcIpAddrStr, &pItem->srcIpAddrOrg); DbgPrint("%s %s session %s %s: %s:%u->%s:%u. State %s->%s\n", timeStr, prefixStr, pItem->out ? "OUT" : "IN ", sufixStr, srcIpAddrStr, RtlUshortByteSwap(pItem->srcPortOrg), dstIpAddrStr, RtlUshortByteSwap(pItem->dstPortOrg), natsState2Name(prevState), natsState2Name(pItem->state) ); }
void net_configure_sandbox_ip(Bridge *br) { assert(br); if (br->configured == 0) return; if (br->arg_ip_none) br->ipsandbox = 0; else if (br->ipsandbox) { // check network range char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); if (rv) { fprintf(stderr, "%s", rv); exit(1); } // send an ARP request and check if there is anybody on this IP address if (arp_check(br->dev, br->ipsandbox, br->ip)) { fprintf(stderr, "Error: IP address %d.%d.%d.%d is already in use\n", PRINT_IP(br->ipsandbox)); exit(1); } } else br->ipsandbox = arp_assign(br->dev, br->ip, br->mask); }
void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) { assert(br); if (br->configured == 0) return; // create a veth pair char *dev; if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0) errExit("asprintf"); net_create_veth(dev, ifname, child); // add interface to the bridge net_bridge_add_interface(br->dev, dev); // bring up the interface net_if_up(dev); char *msg; if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1) errExit("asprintf"); logmsg(msg); fflush(0); free(msg); }
int sandbox(void* sandbox_arg) { if (arg_debug) printf("Initializing child process\n"); //**************************** // wait for the parent to be initialized //**************************** char childstr[BUFLEN + 1]; FILE* stream; close(fds[1]); stream = fdopen(fds[0], "r"); *childstr = '\0'; if (fgets(childstr, BUFLEN, stream)) { // remove \n char *ptr = childstr; while(*ptr !='\0' && *ptr != '\n') ptr++; if (*ptr == '\0') errExit("fgets"); *ptr = '\0'; } else { fprintf(stderr, "Error: cannot establish communication with the parent, exiting...\n"); exit(1); } close(fds[0]); if (arg_debug && getpid() == 1) printf("PID namespace installed\n"); //**************************** // set hostname //**************************** if (cfg.hostname) { if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0) errExit("sethostname"); } //**************************** // mount namespace //**************************** // mount events are not forwarded between the host the sandbox if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { // if we are starting firejail inside firejail, we don't care about this char *mycont = getenv("container"); if (mycont == NULL) errExit("mounting filesystem as slave"); if (strcmp(mycont, "firejail") != 0) errExit("mounting filesystem as slave"); } //**************************** // trace pre-install //**************************** if (arg_trace) fs_trace_preload(); //**************************** // configure filesystem //**************************** int drop_caps = 0; if (cfg.chrootdir) { fs_chroot(cfg.chrootdir); // force caps and seccomp if not started as root if (getuid() != 0) { arg_seccomp = 1; arg_caps = 0; drop_caps = 1; printf("Dropping all Linux capabilities and enforcing default seccomp filter\n"); } //**************************** // trace pre-install, this time inside chroot //**************************** if (arg_trace) fs_trace_preload(); } else if (arg_overlay) fs_overlayfs(); else fs_basic_fs(); //**************************** // set hostname in /etc/hostname //**************************** if (cfg.hostname) { fs_hostname(cfg.hostname); } //**************************** // apply the profile file //**************************** if (cfg.profile) fs_blacklist(cfg.homedir); //**************************** // private mode //**************************** if (arg_private) { if (cfg.home_private) fs_private_home(); else fs_private(); } //**************************** // install trace //**************************** if (arg_trace) fs_trace(); //**************************** // update /proc, /dev, /boot directory //**************************** fs_proc_sys_dev_boot(); //**************************** // networking //**************************** if (arg_nonetwork) { net_if_up("lo"); } else if (arg_noip) { net_if_up("lo"); if (cfg.bridge0.configured) net_if_up("eth0"); if (cfg.bridge1.configured) net_if_up("eth1"); if (cfg.bridge2.configured) net_if_up("eth2"); if (cfg.bridge3.configured) net_if_up("eth3"); } else if (any_bridge_configured()) { // configure lo and eth0...eth3 net_if_up("lo"); if (cfg.bridge0.configured) { Bridge *br = &cfg.bridge0; net_if_up("eth0"); assert(br->ipaddress); if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface eth0\n", PRINT_IP(br->ipaddress)); net_if_ip("eth0", br->ipaddress, br->mask); net_if_up("eth0"); } if (cfg.bridge1.configured) { Bridge *br = &cfg.bridge1; net_if_up("eth1"); assert(br->ipaddress); if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface eth1\n", PRINT_IP(br->ipaddress)); net_if_ip("eth1", br->ipaddress, br->mask); net_if_up("eth1"); } if (cfg.bridge2.configured) { Bridge *br = &cfg.bridge2; net_if_up("eth2"); assert(br->ipaddress); if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface eth2\n", PRINT_IP(br->ipaddress)); net_if_ip("eth2", br->ipaddress, br->mask); net_if_up("eth2"); } if (cfg.bridge3.configured) { Bridge *br = &cfg.bridge3; net_if_up("eth3"); assert(br->ipaddress); if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface eth3\n", PRINT_IP(br->ipaddress)); net_if_ip("eth3", br->ipaddress, br->mask); net_if_up("eth3"); } // add a default route if (!cfg.defaultgw) { // set the default route as IP address of first bridge cfg.defaultgw = cfg.bridge0.ip; if (arg_debug) printf("Using first bridge address as default route\n"); } if (net_add_route(0, 0, cfg.defaultgw)) fprintf(stderr, "Warning: cannot configure default route\n"); if (arg_debug) printf("Network namespace enabled\n"); } net_ifprint(); //**************************** // start executable //**************************** prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died int cwd = 0; if (cfg.cwd) { if (chdir(cfg.cwd) == 0) cwd = 1; } if (!cwd) { if (chdir("/") < 0) errExit("chdir"); if (cfg.homedir) { struct stat s; if (stat(cfg.homedir, &s) == 0) { if (chdir(cfg.homedir) < 0) errExit("chdir"); } } } // set environment // fix qt 4.8 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0) errExit("setenv"); if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc, errExit("setenv"); if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0) errExit("setenv"); if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0) errExit("setenv"); if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0) errExit("setenv"); // set prompt color to green //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) errExit("setenv"); // set capabilities if (arg_caps == 1) caps_filter(); if (drop_caps) caps_drop_all(); // set rlimits set_rlimits(); // set seccomp #ifdef HAVE_SECCOMP if (arg_seccomp == 1) seccomp_filter(); #endif // drop privileges drop_privs(); // set the shell char *sh; if (cfg.shell) sh = cfg.shell; else if (arg_zsh) sh = "/usr/bin/zsh"; else if (arg_csh) sh = "/bin/csh"; else sh = "/bin/bash"; char *arg[4]; arg[0] = sh; arg[1] = "-c"; assert(cfg.command_line); if (arg_debug) printf("Starting %s\n", cfg.command_line); arg[2] = cfg.command_line; arg[3] = NULL; if (!arg_command) printf("Child process initialized\n"); if (arg_debug) { char *msg; if (asprintf(&msg, "child pid %s, execvp into %s", childstr, cfg.command_line) == -1) errExit("asprintf"); logmsg(msg); free(msg); } execvp(sh, arg); perror("execvp"); return 0; }
int sandbox(void* sandbox_arg) { // Get rid of unused parameter warning (void)sandbox_arg; pid_t child_pid = getpid(); if (arg_debug) printf("Initializing child process\n"); // close each end of the unused pipes close(parent_to_child_fds[1]); close(child_to_parent_fds[0]); // wait for parent to do base setup wait_for_other(parent_to_child_fds[0]); if (arg_debug && child_pid == 1) printf("PID namespace installed\n"); //**************************** // set hostname //**************************** if (cfg.hostname) { if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0) errExit("sethostname"); } //**************************** // mount namespace //**************************** // mount events are not forwarded between the host the sandbox if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { chk_chroot(); } //**************************** // log sandbox data //**************************** if (cfg.name) fs_logger2("sandbox name:", cfg.name); fs_logger2int("sandbox pid:", (int) sandbox_pid); if (cfg.chrootdir) fs_logger("sandbox filesystem: chroot"); else if (arg_overlay) fs_logger("sandbox filesystem: overlay"); else fs_logger("sandbox filesystem: local"); fs_logger("install mount namespace"); //**************************** // netfilter etc. //**************************** if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter netfilter(arg_netfilter_file); } if (arg_netfilter6 && any_bridge_configured()) { // assuming by default the client filter netfilter6(arg_netfilter6_file); } // load IBUS env variables if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { // do nothing - there are problems with ibus version 1.5.11 } else env_ibus_load(); // grab a copy of cp command fs_build_cp_command(); // trace pre-install if (arg_trace || arg_tracelog) fs_trace_preload(); //**************************** // configure filesystem //**************************** #ifdef HAVE_SECCOMP int enforce_seccomp = 0; #endif #ifdef HAVE_CHROOT if (cfg.chrootdir) { fs_chroot(cfg.chrootdir); // redo cp command fs_build_cp_command(); // force caps and seccomp if not started as root if (getuid() != 0) { // force default seccomp inside the chroot, no keep or drop list // the list build on top of the default drop list is kept intact arg_seccomp = 1; #ifdef HAVE_SECCOMP enforce_seccomp = 1; #endif if (cfg.seccomp_list_drop) { free(cfg.seccomp_list_drop); cfg.seccomp_list_drop = NULL; } if (cfg.seccomp_list_keep) { free(cfg.seccomp_list_keep); cfg.seccomp_list_keep = NULL; } // disable all capabilities if (arg_caps_default_filter || arg_caps_list) fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n"); arg_caps_drop_all = 1; // drop all supplementary groups; /etc/group file inside chroot // is controlled by a regular usr arg_nogroups = 1; if (!arg_quiet) printf("Dropping all Linux capabilities and enforcing default seccomp filter\n"); } else arg_seccomp = 1; //**************************** // trace pre-install, this time inside chroot //**************************** if (arg_trace || arg_tracelog) fs_trace_preload(); } else #endif if (arg_overlay) fs_overlayfs(); else fs_basic_fs(); //**************************** // set hostname in /etc/hostname //**************************** if (cfg.hostname) { fs_hostname(cfg.hostname); } //**************************** // private mode //**************************** if (arg_private) { if (cfg.home_private) // --private= fs_private_homedir(); else // --private fs_private(); } if (arg_private_dev) fs_private_dev(); if (arg_private_etc) { fs_private_etc_list(); // create /etc/ld.so.preload file again if (arg_trace || arg_tracelog) fs_trace_preload(); } if (arg_private_bin) fs_private_bin_list(); if (arg_private_tmp) fs_private_tmp(); //**************************** // apply the profile file //**************************** if (cfg.profile) { // apply all whitelist commands ... fs_whitelist(); // ... followed by blacklist commands fs_blacklist(); } //**************************** // install trace //**************************** if (arg_trace || arg_tracelog) fs_trace(); //**************************** // update /proc, /dev, /boot directorymy //**************************** fs_proc_sys_dev_boot(); //**************************** // --nosound and fix for pulseaudio 7.0 //**************************** if (arg_nosound) pulseaudio_disable(); else pulseaudio_init(); //**************************** // networking //**************************** if (arg_nonetwork) { net_if_up("lo"); if (arg_debug) printf("Network namespace enabled, only loopback interface available\n"); } else if (any_bridge_configured() || any_interface_configured()) { // configure lo and eth0...eth3 net_if_up("lo"); if (mac_not_zero(cfg.bridge0.macsandbox)) net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); sandbox_if_up(&cfg.bridge0); if (mac_not_zero(cfg.bridge1.macsandbox)) net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); sandbox_if_up(&cfg.bridge1); if (mac_not_zero(cfg.bridge2.macsandbox)) net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); sandbox_if_up(&cfg.bridge2); if (mac_not_zero(cfg.bridge3.macsandbox)) net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); sandbox_if_up(&cfg.bridge3); // add a default route if (cfg.defaultgw) { // set the default route if (net_add_route(0, 0, cfg.defaultgw)) fprintf(stderr, "Warning: cannot configure default route\n"); } // enable interfaces if (cfg.interface0.configured && cfg.interface0.ip) { if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev); net_if_ip(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu); net_if_up(cfg.interface0.dev); } if (cfg.interface1.configured && cfg.interface1.ip) { if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev); net_if_ip(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu); net_if_up(cfg.interface1.dev); } if (cfg.interface2.configured && cfg.interface2.ip) { if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev); net_if_ip(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu); net_if_up(cfg.interface2.dev); } if (cfg.interface3.configured && cfg.interface3.ip) { if (arg_debug) printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev); net_if_ip(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu); net_if_up(cfg.interface3.dev); } if (arg_debug) printf("Network namespace enabled\n"); } // if any dns server is configured, it is time to set it now fs_resolvconf(); fs_logger_print(); fs_logger_change_owner(); // print network configuration if (!arg_quiet) { if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) { printf("\n"); if (any_bridge_configured() || any_interface_configured()) net_ifprint(); if (cfg.defaultgw != 0) printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw)); if (cfg.dns1 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); if (cfg.dns2 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); if (cfg.dns3 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); printf("\n"); } } fs_delete_cp_command(); //**************************** // set application environment //**************************** prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died int cwd = 0; if (cfg.cwd) { if (chdir(cfg.cwd) == 0) cwd = 1; } if (!cwd) { if (chdir("/") < 0) errExit("chdir"); if (cfg.homedir) { struct stat s; if (stat(cfg.homedir, &s) == 0) { /* coverity[toctou] */ if (chdir(cfg.homedir) < 0) errExit("chdir"); } } } // set environment env_defaults(); // set user-supplied environment variables env_apply(); // set nice if (arg_nice) { errno = 0; int rv = nice(cfg.nice); (void) rv; if (errno) { fprintf(stderr, "Warning: cannot set nice value\n"); errno = 0; } } // clean /tmp/.X11-unix sockets fs_x11(); //**************************** // set security filters //**************************** // set capabilities if (!arg_noroot) set_caps(); // set rlimits set_rlimits(); // set seccomp #ifdef HAVE_SECCOMP // install protocol filter if (cfg.protocol) { protocol_filter(); // install filter protocol_filter_save(); // save filter in PROTOCOL_CFG } // if a keep list is available, disregard the drop list if (arg_seccomp == 1) { if (cfg.seccomp_list_keep) seccomp_filter_keep(); else if (cfg.seccomp_list_errno) seccomp_filter_errno(); else seccomp_filter_drop(enforce_seccomp); } #endif // set cpu affinity if (cfg.cpus) { save_cpu(); // save cpu affinity mask to CPU_CFG file set_cpu_affinity(); } // save cgroup in CGROUP_CFG file if (cfg.cgroup) save_cgroup(); //**************************************** // drop privileges or create a new user namespace //**************************************** save_nogroups(); if (arg_noroot) { int rv = unshare(CLONE_NEWUSER); if (rv == -1) { fprintf(stderr, "Error: cannot mount a new user namespace\n"); perror("unshare"); drop_privs(arg_nogroups); } } else drop_privs(arg_nogroups); // notify parent that new user namespace has been created so a proper // UID/GID map can be setup notify_other(child_to_parent_fds[1]); close(child_to_parent_fds[1]); // wait for parent to finish setting up a proper UID/GID map wait_for_other(parent_to_child_fds[0]); close(parent_to_child_fds[0]); // somehow, the new user namespace resets capabilities; // we need to do them again if (arg_noroot) { set_caps(); if (arg_debug) printf("noroot user namespace installed\n"); } //**************************************** // fork the application and monitor it //**************************************** pid_t app_pid = fork(); if (app_pid == -1) errExit("fork"); if (app_pid == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died start_application(); // start app } monitor_application(app_pid); // monitor application return 0; }
// the default address should be in the range of at least on of the bridge devices void check_default_gw(uint32_t defaultgw) { assert(defaultgw); if (cfg.bridge0.configured) { char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask); if (rv == 0) return; } if (cfg.bridge1.configured) { char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask); if (rv == 0) return; } if (cfg.bridge2.configured) { char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask); if (rv == 0) return; } if (cfg.bridge3.configured) { char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask); if (rv == 0) return; } fprintf(stderr, "Error: default gateway %d.%d.%d.%d is not in the range of any network\n", PRINT_IP(defaultgw)); exit(1); }
VOID PrintFtlPkt( IN char *strPrefix, IN FLT_PKT* pFltPkt, IN ULONG uNewIp, IN BOOLEAN bOut ) { TIME_FIELDS TimeFields; char Message[255]; char MessagePart[30]; LARGE_INTEGER time; KeQuerySystemTime(&time); ExSystemTimeToLocalTime(&time, &time); RtlTimeToTimeFields(&time, &TimeFields); RtlStringCbPrintfA(Message, sizeof(Message), "%02d:%02d:%02d.%03d ", TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds); if (!bOut) { RtlStringCbCatA(Message, sizeof(Message), "IN "); } else { RtlStringCbCatA(Message, sizeof(Message), "OUT "); } RtlStringCbCatA(Message, sizeof(Message), strPrefix); RtlStringCbCatA(Message, sizeof(Message), " "); if (NULL == pFltPkt->pEth) { goto out; } RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x", pFltPkt->pEth->ether_src[0], pFltPkt->pEth->ether_src[1], pFltPkt->pEth->ether_src[2], pFltPkt->pEth->ether_src[3], pFltPkt->pEth->ether_src[4], pFltPkt->pEth->ether_src[5]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "->"); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x", pFltPkt->pEth->ether_dst[0], pFltPkt->pEth->ether_dst[1], pFltPkt->pEth->ether_dst[2], pFltPkt->pEth->ether_dst[3], pFltPkt->pEth->ether_dst[4], pFltPkt->pEth->ether_dst[5]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); switch (pFltPkt->pEth->ether_type) { case ETHERNET_TYPE_ARP_NET: RtlStringCbCatA(Message, sizeof(Message), " ARP "); if (NULL == pFltPkt->pArp) goto out; if (ARP_REQUEST_CODE == pFltPkt->pArp->ea_hdr.ar_op) { RtlStringCbCatA(Message, sizeof(Message), "Request "); } else if (pFltPkt->pArp->ea_hdr.ar_op == ARP_REPLY_CODE) { RtlStringCbCatA(Message, sizeof(Message), "Reply "); } RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%d.%d.%d.%d", pFltPkt->pArp->arp_spa[0], pFltPkt->pArp->arp_spa[1], pFltPkt->pArp->arp_spa[2], pFltPkt->pArp->arp_spa[3]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "->"); PRINT_IP(MessagePart, pFltPkt->pArp->arp_tpa); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; case ETHERNET_TYPE_IP_NET: RtlStringCbCatA(Message, sizeof(Message), " IP "); if (NULL == pFltPkt->pIp) goto out; RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "ID %04x ", RtlUshortByteSwap(pFltPkt->pIp->ip_id)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); PRINT_IP(MessagePart, &pFltPkt->pIp->ip_src); RtlStringCbCatA(Message, sizeof(Message), MessagePart); if (uNewIp && bOut) { RtlStringCbCatA(Message, sizeof(Message), "["); PRINT_IP(MessagePart, &uNewIp); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "]"); } RtlStringCbCatA(Message, sizeof(Message), "->"); PRINT_IP(MessagePart, &pFltPkt->pIp->ip_dst); RtlStringCbCatA(Message, sizeof(Message), MessagePart); if (uNewIp && !bOut) { RtlStringCbCatA(Message, sizeof(Message), "["); PRINT_IP(MessagePart, &uNewIp); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "]"); } switch (pFltPkt->pIp->ip_proto) { case IPPROTO_TCP: RtlStringCbCatA(Message, sizeof(Message), " TCP"); break; case IPPROTO_ICMP: RtlStringCbCatA(Message, sizeof(Message), " ICMP"); break; case IPPROTO_UDP: RtlStringCbCatA(Message, sizeof(Message), " UDP"); break; default: RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " proto=%04x", pFltPkt->pIp->ip_proto); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; } if (pFltPkt->pTcp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d ", RtlUshortByteSwap(pFltPkt->pTcp->th_sport), RtlUshortByteSwap(pFltPkt->pTcp->th_dport)); if (pFltPkt->pTcp->th_flags & TCP_FIN_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "F"); if (pFltPkt->pTcp->th_flags & TCP_SYN_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "S"); if (pFltPkt->pTcp->th_flags & TCP_RST_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "R"); if (pFltPkt->pTcp->th_flags & TCP_PSH_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "P"); if (pFltPkt->pTcp->th_flags & TCP_URG_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "U"); if (pFltPkt->pTcp->th_flags & TCP_ACK_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "A"); // https://tools.ietf.org/html/rfc3168 if (pFltPkt->pTcp->th_flags & TCP_ECE_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "E"); if (pFltPkt->pTcp->th_flags & TCP_CWR_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "C"); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " SEQ:%u", RtlUlongByteSwap(pFltPkt->pTcp->th_seq)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " ACK:%u", RtlUlongByteSwap(pFltPkt->pTcp->th_ack)); } else if (pFltPkt->pUdp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d", RtlUshortByteSwap(pFltPkt->pUdp->uh_sport), RtlUshortByteSwap(pFltPkt->pUdp->uh_dport)); } else if (pFltPkt->pIcmp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d", RtlUshortByteSwap(pFltPkt->pIcmp->icmp_hun.idseq.id)); } else { MessagePart[0] = 0; } RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; default: RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " UNK %04x", RtlUshortByteSwap(pFltPkt->pEth->ether_type)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; } out: RtlStringCbCatA(Message, sizeof(Message), "\n"); DbgPrint(Message); return; }
// returns 0 if the address is not in use, -1 otherwise int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) { if (strlen(dev) > IFNAMSIZ) { fprintf(stderr, "Error: invalid network device name %s\n", dev); exit(1); } if (arg_debug) printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr)); // find interface address int sock; if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) errExit("socket"); srcaddr = htonl(srcaddr); destaddr = htonl(destaddr); // Find interface MAC address struct ifreq ifr; memset(&ifr, 0, sizeof (ifr)); strncpy(ifr.ifr_name, dev, IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) errExit("ioctl"); close(sock); // configure layer2 socket address information struct sockaddr_ll addr; memset(&addr, 0, sizeof(addr)); if ((addr.sll_ifindex = if_nametoindex(dev)) == 0) errExit("if_nametoindex"); addr.sll_family = AF_PACKET; memcpy (addr.sll_addr, ifr.ifr_hwaddr.sa_data, 6); addr.sll_halen = htons(6); // build the arp packet header ArpHdr hdr; memset(&hdr, 0, sizeof(hdr)); hdr.htype = htons(1); hdr.ptype = htons(ETH_P_IP); hdr.hlen = 6; hdr.plen = 4; hdr.opcode = htons(1); //ARPOP_REQUEST memcpy(hdr.sender_mac, ifr.ifr_hwaddr.sa_data, 6); memcpy(hdr.sender_ip, (uint8_t *)&srcaddr, 4); memcpy(hdr.target_ip, (uint8_t *)&destaddr, 4); // buiild ethernet frame uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc memset(frame, 0, sizeof(frame)); frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff; memcpy(frame + 6, ifr.ifr_hwaddr.sa_data, 6); frame[12] = ETH_P_ARP / 256; frame[13] = ETH_P_ARP % 256; memcpy (frame + 14, &hdr, sizeof(hdr)); // open layer2 socket if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) errExit("socket"); int len; if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0) errExit("send"); fflush(0); // wait not more than one second for an answer fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); int maxfd = sock; struct timeval ts; ts.tv_sec = 1; // 1 second wait time ts.tv_usec = 0; while (1) { int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts); if (nready < 0) errExit("select"); else if (nready == 0) { // timeout close(sock); return 0; } else { // read the incoming packet int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL); if (len < 0) { perror("recvfrom"); close(sock); return -1; } // parse the incomming packet if ((unsigned int) len < 14 + sizeof(ArpHdr)) continue; if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256)) continue; memcpy(&hdr, frame + 14, sizeof(ArpHdr)); if (hdr.opcode == htons(1)) continue; if (hdr.opcode == htons(2)) { // check my mac and my address if (memcmp(ifr.ifr_hwaddr.sa_data, hdr.target_mac, 6) != 0) continue; uint32_t ip; memcpy(&ip, hdr.target_ip, 4); if (ip != srcaddr) { continue; } close(sock); return -1; } } } // it will never get here! close(sock); return -1; }
// scan interface (--scan option) void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) { assert(dev); assert(ifip); // printf("Scanning interface %s (%d.%d.%d.%d/%d)\n", // dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask)); if (strlen(dev) > IFNAMSIZ) { fprintf(stderr, "Error: invalid network device name %s\n", dev); exit(1); } // find interface mac address int sock; if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) errExit("socket"); struct ifreq ifr; memset(&ifr, 0, sizeof (ifr)); strncpy(ifr.ifr_name, dev, IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) errExit("ioctl"); close(sock); uint8_t mac[6]; memcpy (mac, ifr.ifr_hwaddr.sa_data, 6); // open layer2 socket if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) errExit("socket"); // try all possible ip addresses in ascending order uint32_t range = ~ifmask + 1; // the number of potential addresses // this software is not supported for /31 networks if (range < 4) { fprintf(stderr, "Warning: this option is not supported for /31 networks\n"); close(sock); return; } uint32_t dest = (ifip & ifmask) + 1; uint32_t last = dest + range - 1; uint32_t src = htonl(ifip); // wait not more than one second for an answer int header_printed = 0; uint32_t last_ip = 0; struct timeval ts; ts.tv_sec = 2; // 2 seconds receive timeout ts.tv_usec = 0; while (1) { fd_set rfds; FD_ZERO(&rfds); FD_SET(sock, &rfds); fd_set wfds; FD_ZERO(&wfds); FD_SET(sock, &wfds); int maxfd = sock; uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc memset(frame, 0, ETH_FRAME_LEN); int nready; if (dest < last) nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL); else nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts); if (nready < 0) errExit("select"); if (nready == 0) { // timeout break; } if (FD_ISSET(sock, &wfds) && dest < last) { // configure layer2 socket address information struct sockaddr_ll addr; memset(&addr, 0, sizeof(addr)); if ((addr.sll_ifindex = if_nametoindex(dev)) == 0) errExit("if_nametoindex"); addr.sll_family = AF_PACKET; memcpy (addr.sll_addr, mac, 6); addr.sll_halen = htons(6); // build the arp packet header ArpHdr hdr; memset(&hdr, 0, sizeof(hdr)); hdr.htype = htons(1); hdr.ptype = htons(ETH_P_IP); hdr.hlen = 6; hdr.plen = 4; hdr.opcode = htons(1); //ARPOP_REQUEST memcpy(hdr.sender_mac, mac, 6); memcpy(hdr.sender_ip, (uint8_t *)&src, 4); uint32_t dst = htonl(dest); memcpy(hdr.target_ip, (uint8_t *)&dst, 4); // buiild ethernet frame uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc memset(frame, 0, sizeof(frame)); frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff; memcpy(frame + 6, mac, 6); frame[12] = ETH_P_ARP / 256; frame[13] = ETH_P_ARP % 256; memcpy (frame + 14, &hdr, sizeof(hdr)); // send packet int len; if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0) errExit("send"); //printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest)); fflush(0); dest++; } if (FD_ISSET(sock, &rfds)) { // read the incoming packet int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL); if (len < 0) { perror("recvfrom"); } // parse the incomming packet if ((unsigned int) len < 14 + sizeof(ArpHdr)) continue; // look only at ARP packets if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256)) continue; ArpHdr hdr; memcpy(&hdr, frame + 14, sizeof(ArpHdr)); if (hdr.opcode == htons(2)) { // check my mac and my address if (memcmp(mac, hdr.target_mac, 6) != 0) continue; uint32_t ip; memcpy(&ip, hdr.target_ip, 4); if (ip != src) continue; memcpy(&ip, hdr.sender_ip, 4); ip = ntohl(ip); if (ip == last_ip) // filter duplicates continue; last_ip = ip; // printing if (header_printed == 0) { printf(" Network scan:\n"); // print parent interface if (cfg.bridge0.configured && cfg.bridge0.ip && cfg.bridge0.macvlan && (cfg.bridge0.ip & cfg.bridge0.mask) == (ifip & cfg.bridge0.mask)) printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", PRINT_MAC(cfg.bridge0.mac), PRINT_IP(cfg.bridge0.ip)); if (cfg.bridge1.configured && cfg.bridge1.ip && cfg.bridge1.macvlan && (cfg.bridge1.ip & cfg.bridge1.mask) == (ifip & cfg.bridge1.mask)) printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", PRINT_MAC(cfg.bridge1.mac), PRINT_IP(cfg.bridge1.ip)); if (cfg.bridge2.configured && cfg.bridge2.ip && cfg.bridge2.macvlan && (cfg.bridge2.ip & cfg.bridge2.mask) == (ifip & cfg.bridge2.mask)) printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", PRINT_MAC(cfg.bridge2.mac), PRINT_IP(cfg.bridge2.ip)); if (cfg.bridge3.configured && cfg.bridge3.ip && cfg.bridge3.macvlan && (cfg.bridge3.ip & cfg.bridge3.mask) == (ifip & cfg.bridge3.mask)) printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", PRINT_MAC(cfg.bridge3.mac), PRINT_IP(cfg.bridge3.ip)); header_printed = 1; } printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", PRINT_MAC(hdr.sender_mac), PRINT_IP(ip)); } } } close(sock); }
// print IP addresses for all interfaces static void net_ifprint(void) { uint32_t ip; uint32_t mask; struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == -1) errExit("getifaddrs"); // walk through the linked list printf(" Link status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_PACKET) { if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) { if (ifa->ifa_data != NULL) { struct rtnl_link_stats *stats = ifa->ifa_data; printf(" %s UP - tx/rx: %u/%u packets, %u/%u bytes\n", ifa->ifa_name, stats->tx_packets, stats->rx_packets, stats->tx_bytes, stats->rx_bytes); } } else printf(" %s DOWN\n", ifa->ifa_name); } } // walk through the linked list printf(" IPv4 status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask; mask = ntohl(si->sin_addr.s_addr); si = (struct sockaddr_in *) ifa->ifa_addr; ip = ntohl(si->sin_addr.s_addr); char *status; if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) status = "UP"; else status = "DOWN"; printf(" %s %s, %d.%d.%d.%d/%u\n", ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask)); } } // walk through the linked list printf(" IPv6 status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET6) { char host[NI_MAXHOST]; int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s == 0) { char *ptr; if ((ptr = strchr(host, '%')) != NULL) *ptr = '\0'; char *status; if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) status = "UP"; else status = "DOWN"; printf(" %s %s, %s\n", ifa->ifa_name, status, host); } } } freeifaddrs(ifaddr); }
// print IP addresses for all interfaces static void net_ifprint(void) { uint32_t ip; uint32_t mask; struct ifaddrs *ifaddr, *ifa; int fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "Error: cannot open AF_INET socket\n"); exit(1); } if (getifaddrs(&ifaddr) == -1) errExit("getifaddrs"); // walk through the linked list printf(" Link status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_PACKET) { if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) { if (ifa->ifa_data != NULL) { struct rtnl_link_stats *stats = ifa->ifa_data; // extract mac address struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); int rv = ioctl (fd, SIOCGIFHWADDR, &ifr); if (rv == 0) printf(" %s UP, %02x:%02x:%02x:%02x:%02x:%02x\n", ifa->ifa_name, PRINT_MAC((unsigned char *) &ifr.ifr_hwaddr.sa_data)); else printf(" %s UP\n", ifa->ifa_name); printf(" tx/rx: %u/%u packets, %u/%u bytes\n", stats->tx_packets, stats->rx_packets, stats->tx_bytes, stats->rx_bytes); } } else printf(" %s DOWN\n", ifa->ifa_name); } } // walk through the linked list printf(" IPv4 status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask; mask = ntohl(si->sin_addr.s_addr); si = (struct sockaddr_in *) ifa->ifa_addr; ip = ntohl(si->sin_addr.s_addr); char *status; if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) status = "UP"; else status = "DOWN"; printf(" %s %s, %d.%d.%d.%d/%u\n", ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask)); } } // walk through the linked list printf(" IPv6 status:\n"); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET6) { char host[NI_MAXHOST]; int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s == 0) { char *ptr; if ((ptr = strchr(host, '%')) != NULL) *ptr = '\0'; char *status; if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) status = "UP"; else status = "DOWN"; printf(" %s %s, %s\n", ifa->ifa_name, status, host); } } } freeifaddrs(ifaddr); close(fd); }
// scan interfaces in current namespace and print IP address/mask for each interface void net_ifprint(void) { uint32_t ip; uint32_t mask; struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == -1) errExit("getifaddrs"); printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", "Interface", "MAC", "IP", "Mask", "Status"); // walk through the linked list for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask; mask = ntohl(si->sin_addr.s_addr); si = (struct sockaddr_in *) ifa->ifa_addr; ip = ntohl(si->sin_addr.s_addr); // interface status char *status; if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) status = "UP"; else status = "DOWN"; // ip address and mask char ipstr[30]; sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip)); char maskstr[30]; sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask)); // mac address unsigned char mac[6]; net_get_mac(ifa->ifa_name, mac); char macstr[30]; if (strcmp(ifa->ifa_name, "lo") == 0) macstr[0] = '\0'; else sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac)); // print printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", ifa->ifa_name, macstr, ipstr, maskstr, status); // network scanning if (!arg_scan) // scanning disabled continue; if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning continue; if (mask2bits(mask) < 16) // not scanning large networks continue; if (!ip) // if not configured continue; // only if the interface is up and running if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) arp_scan(ifa->ifa_name, ip, mask); } } freeifaddrs(ifaddr); }
int sandbox(void* sandbox_arg) { // Get rid of unused parameter warning (void)sandbox_arg; pid_t child_pid = getpid(); if (arg_debug) printf("Initializing child process\n"); // close each end of the unused pipes close(parent_to_child_fds[1]); close(child_to_parent_fds[0]); // wait for parent to do base setup wait_for_other(parent_to_child_fds[0]); if (arg_debug && child_pid == 1) printf("PID namespace installed\n"); //**************************** // set hostname //**************************** if (cfg.hostname) { if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0) errExit("sethostname"); } //**************************** // mount namespace //**************************** // mount events are not forwarded between the host the sandbox if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { chk_chroot(); } //**************************** // netfilter //**************************** if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter netfilter(arg_netfilter_file); } //**************************** // trace pre-install //**************************** if (arg_trace) fs_trace_preload(); //**************************** // configure filesystem //**************************** #ifdef HAVE_CHROOT if (cfg.chrootdir) { fs_chroot(cfg.chrootdir); // force caps and seccomp if not started as root if (getuid() != 0) { // force default seccomp inside the chroot, no keep or drop list // the list build on top of the default drop list is kept intact arg_seccomp = 1; if (arg_seccomp_list_drop) { free(arg_seccomp_list_drop); arg_seccomp_list_drop = NULL; } if (arg_seccomp_list_keep) { free(arg_seccomp_list_keep); arg_seccomp_list_keep = NULL; } // disable all capabilities if (arg_caps_default_filter || arg_caps_list) fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n"); arg_caps_drop_all = 1; // drop all supplementary groups; /etc/group file inside chroot // is controlled by a regular usr arg_nogroups = 1; printf("Dropping all Linux capabilities and enforcing default seccomp filter\n"); } //**************************** // trace pre-install, this time inside chroot //**************************** if (arg_trace) fs_trace_preload(); } else #endif if (arg_overlay) fs_overlayfs(); else fs_basic_fs(); //**************************** // set hostname in /etc/hostname //**************************** if (cfg.hostname) { fs_hostname(cfg.hostname); } //**************************** // apply the profile file //**************************** if (cfg.profile) fs_blacklist(cfg.homedir); //**************************** // private mode //**************************** if (arg_private) { if (cfg.home_private) // --private= fs_private_homedir(); else if (cfg.home_private_keep) // --private-home= fs_private_home_list(); else // --private fs_private(); } if (arg_private_dev) fs_private_dev(); if (arg_private_etc) fs_private_etc_list(); //**************************** // install trace //**************************** if (arg_trace) fs_trace(); //**************************** // update /proc, /dev, /boot directorymy //**************************** fs_proc_sys_dev_boot(); //**************************** // networking //**************************** if (arg_nonetwork) { net_if_up("lo"); if (arg_debug) printf("Network namespace enabled, only loopback interface available\n"); } else if (any_bridge_configured()) { // configure lo and eth0...eth3 net_if_up("lo"); if (mac_not_zero(cfg.bridge0.macsandbox)) net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); sandbox_if_up(&cfg.bridge0); if (mac_not_zero(cfg.bridge1.macsandbox)) net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); sandbox_if_up(&cfg.bridge1); if (mac_not_zero(cfg.bridge2.macsandbox)) net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); sandbox_if_up(&cfg.bridge2); if (mac_not_zero(cfg.bridge3.macsandbox)) net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); sandbox_if_up(&cfg.bridge3); // add a default route if (cfg.defaultgw) { // set the default route if (net_add_route(0, 0, cfg.defaultgw)) fprintf(stderr, "Warning: cannot configure default route\n"); } if (arg_debug) printf("Network namespace enabled\n"); } // if any dns server is configured, it is time to set it now fs_resolvconf(); // print network configuration if (any_bridge_configured() || cfg.defaultgw || cfg.dns1) { printf("\n"); if (any_bridge_configured()) net_ifprint(); if (cfg.defaultgw != 0) printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw)); if (cfg.dns1 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); if (cfg.dns2 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); if (cfg.dns3 != 0) printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); printf("\n"); } //**************************** // start executable //**************************** prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died int cwd = 0; if (cfg.cwd) { if (chdir(cfg.cwd) == 0) cwd = 1; } if (!cwd) { if (chdir("/") < 0) errExit("chdir"); if (cfg.homedir) { struct stat s; if (stat(cfg.homedir, &s) == 0) { /* coverity[toctou] */ if (chdir(cfg.homedir) < 0) errExit("chdir"); } } } // set environment // fix qt 4.8 if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0) errExit("setenv"); if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc, errExit("setenv"); if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0) errExit("setenv"); if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0) errExit("setenv"); if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0) errExit("setenv"); // set prompt color to green //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) errExit("setenv"); // set user-supplied environment variables env_apply(); // set capabilities if (!arg_noroot) set_caps(); // set rlimits set_rlimits(); // set seccomp #ifdef HAVE_SECCOMP // if a keep list is available, disregard the drop list if (arg_seccomp == 1) { if (arg_seccomp_list_keep) seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file else seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file } #endif // set cpu affinity if (cfg.cpus) { save_cpu(); // save cpu affinity mask to MNT_DIR/cpu file set_cpu_affinity(); } // save cgroup in MNT_DIR/cgroup file if (cfg.cgroup) save_cgroup(); //**************************************** // drop privileges or create a new user namespace //**************************************** save_nogroups(); if (arg_noroot) { int rv = unshare(CLONE_NEWUSER); if (rv == -1) { fprintf(stderr, "Error: cannot mount a new user namespace\n"); perror("unshare"); drop_privs(arg_nogroups); } } else drop_privs(arg_nogroups); // notify parent that new user namespace has been created so a proper // UID/GID map can be setup notify_other(child_to_parent_fds[1]); close(child_to_parent_fds[1]); // wait for parent to finish setting up a proper UID/GID map wait_for_other(parent_to_child_fds[0]); close(parent_to_child_fds[0]); // somehow, the new user namespace resets capabilities; // we need to do them again if (arg_noroot) { set_caps(); if (arg_debug) printf("User namespace (noroot) installed\n"); } //**************************************** // start the program without using a shell //**************************************** if (arg_shell_none) { if (arg_debug) { int i; for (i = cfg.original_program_index; i < cfg.original_argc; i++) { if (cfg.original_argv[i] == NULL) break; printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]); } } if (!arg_command) printf("Child process initialized\n"); execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); } //**************************************** // start the program using a shell //**************************************** else { // choose the shell requested by the user, or use bash as default char *sh; if (cfg.shell) sh = cfg.shell; else if (arg_zsh) sh = "/usr/bin/zsh"; else if (arg_csh) sh = "/bin/csh"; else sh = "/bin/bash"; char *arg[5]; int index = 0; arg[index++] = sh; arg[index++] = "-c"; assert(cfg.command_line); if (arg_debug) printf("Starting %s\n", cfg.command_line); if (arg_doubledash) arg[index++] = "--"; arg[index++] = cfg.command_line; arg[index] = NULL; assert(index < 5); if (arg_debug) { char *msg; if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) errExit("asprintf"); logmsg(msg); free(msg); } if (arg_debug) { int i; for (i = 0; i < 5; i++) { if (arg[i] == NULL) break; printf("execvp argument %d: %s\n", i, arg[i]); } } if (!arg_command) printf("Child process initialized\n"); execvp(sh, arg); } perror("execvp"); return 0; }
static void print_route(const char *fname) { FILE *fp = fopen(fname, "r"); if (!fp) return; printf(" Route table:\n"); char buf[MAXBUF]; while (fgets(buf, MAXBUF, fp)) { // remove blanks, \n char *ptr = buf; while (*ptr == ' ' || *ptr == '\t') ptr++; char *start = ptr; if (*start == '\0') continue; ptr = strchr(ptr, '\n'); if (ptr) *ptr = '\0'; // remove table header //Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT if (strncmp(start, "Iface", 5) == 0) continue; // extract data char ifname[64]; char destination[64]; char gateway[64]; char flags[64]; char refcnt[64]; char use[64]; char metric[64]; char mask[64]; int rv = sscanf(start, "%s %s %s %s %s %s %s %s\n", ifname, destination, gateway, flags, refcnt, use, metric, mask); if (rv != 8) continue; // destination ip uint32_t destip; sscanf(destination, "%x", &destip); destip = ntohl(destip); uint32_t destmask; sscanf(mask, "%x", &destmask); destmask = ntohl(destmask); uint32_t gw; sscanf(gateway, "%x", &gw); gw = ntohl(gw); // printf("#%s# #%s# #%s# #%s# #%s# #%s# #%s# #%s#\n", ifname, destination, gateway, flags, refcnt, use, metric, mask); if (gw != 0) printf(" %u.%u.%u.%u/%u via %u.%u.%u.%u, dev %s, metric %s\n", PRINT_IP(destip), mask2bits(destmask), PRINT_IP(gw), ifname, metric); else { // this is an interface IfList *ifentry = list_find(destip, destmask); if (ifentry) { printf(" %u.%u.%u.%u/%u, dev %s, scope link src %d.%d.%d.%d\n", PRINT_IP(destip), mask2bits(destmask), ifname, PRINT_IP(ifentry->ip)); } } } fclose(fp); }