void AutoBan::setFromConf(){ char* banIps = g_conf.m_banIps; char *start = banIps; do { while(*banIps && !isspace(*banIps)) banIps++; long ip = atoip(start, banIps - start); if(ip) { if(!addIp(ip, DENY)) { log(LOG_WARN, "autoban: malloc failed, couldn't add IP."); } } while(*banIps && isspace(*banIps)) banIps++; start = banIps; } while(*banIps); char* allowIps = g_conf.m_allowIps; start = allowIps; do { while(*allowIps && !isspace(*allowIps)) allowIps++; long ip = atoip(start, allowIps - start); if(ip) { if(!addIp(ip, ALLOW)) { log(LOG_WARN, "autoban: malloc failed, couldn't add IP."); } } while(*allowIps && isspace(*allowIps)) allowIps++; start = allowIps; } while(*allowIps); }
int CLiveList::SortProc(LPCTSTR sB, LPCTSTR sA, BOOL bNumeric) { // ToDo: Fix Click-order properly (Revert above sB-sA workaround!) DWORD ipA, ipB; if ( atoip( sA, ipA ) && atoip( sB, ipB ) ) { TCHAR* pA = (TCHAR*)_tcschr( sA, '/' ); TCHAR* pB = (TCHAR*)_tcschr( sB, '/' ); DWORD maskA = 0xffffffff, maskB = 0xffffffff; if ( ( ! pA || atoip( pA + 1, maskA ) ) && ( ! pB || atoip( pB + 1, maskB ) ) ) { QWORD nA = ( ( (QWORD) ipA ) << 32 ) | maskA; QWORD nB = ( ( (QWORD) ipB ) << 32 ) | maskB; if ( nA < nB ) return -1; if ( nA > nB ) return 1; return 0; } } if ( bNumeric || ( IsNumber( sA ) && IsNumber( sB ) ) ) { double nA = 0, nB = 0; if ( *sA == '(' || *sA == 'Q' ) _stscanf( sA+1, _T("%lf"), &nA ); else _stscanf( sA, _T("%lf (%lf)"), &nA, &nA ); if ( *sB == '(' || *sB == 'Q' ) _stscanf( sB+1, _T("%lf"), &nB ); else _stscanf( sB, _T("%lf (%lf)"), &nB, &nB ); if ( _tcsstr( sA, _T(" K") ) ) nA *= 1024; if ( _tcsstr( sA, _T(" M") ) ) nA *= 1024*1024; if ( _tcsstr( sA, _T(" G") ) ) nA *= 1024*1024*1024; if ( _tcsstr( sA, _T(" T") ) ) nA *= 1099511627776.0f; if ( _tcsstr( sB, _T(" K") ) ) nB *= 1024; if ( _tcsstr( sB, _T(" M") ) ) nB *= 1024*1024; if ( _tcsstr( sB, _T(" G") ) ) nB *= 1024*1024*1024; if ( _tcsstr( sB, _T(" T") ) ) nB *= 1099511627776.0f; if ( nB < nA ) return -1; if ( nB > nA ) return 1; return 0; } return _tcsicoll( sA, sB ); }
int cliLoggingHostCmd(CliMode mode, int argc, char **argv) { char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // cleaning the return string // no command if (strcmp("no", argv[0]) == 0) { // extract address uint32_t ip; if (atoip(argv[3], &ip)) { strcpy(data, "Error: invalid IP address"); return RCPERR; } RcpSyslogHost *found = host_find(ip); if (found == NULL) return 0; found->valid = 0; } else { // extract address and port uint32_t ip; if (atoip(argv[2], &ip)) { strcpy(data, "Error: invalid IP address"); return RCPERR; } uint16_t port = 0; if (argc == 5) { int p = atoi(argv[4]); port = (uint16_t) p; } RcpSyslogHost *found = host_find(ip); if (found != NULL) { // modify existing host found->port = port; return 0; } // set a new host RcpSyslogHost *newhost = host_find_empty(); if (newhost == NULL) { strcpy(data, "Error: cannot configure host, limit reached\n"); return RCPERR; } memset(newhost, 0, sizeof(RcpSyslogHost)); newhost->ip = ip; newhost->port = port; newhost->valid = 1; } return 0; }
int main (int argc, char *argv[]) { unsigned long ipaddr; char logtext[1024]; logtext[0] = 0; logtext[1023] = 0; int i; if (argc<3) { fprintf (stderr, "Usage: %s <ip> <text>", argv[0]); return 1; } ipaddr = atoip (argv[1]); if (! ipaddr) { fprintf (stderr, "Unknown address: %s\n", argv[1]); return 1; } for (i=2; i<argc; ++i) { if (i>2) strncat (logtext, " ", 1023); strncat (logtext, argv[i], 1023); } hostlog (ipaddr, ST_UNSET, ST_UNSET, 0, logtext); return 0; }
int cliNoIpRouteCidrCmd(CliMode mode, int argc, char **argv) { char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // extract data uint32_t ip; uint32_t mask; if (atocidr(argv[3], &ip, &mask)) { strcpy(data, "Error: invalid IP address\n"); return RCPERR; } // this should be a network address if (ip & (~mask)) { strcpy(data, "Error: invalid IP address\n"); return RCPERR; } uint32_t gw; if (atoip(argv[4], &gw)) { strcpy(data, "Error: invalid next hop address\n"); return RCPERR; } // delete route rcpDelRoute(muxsock, ip, mask, gw); redistribute_route(SIOCDELRT, ip, mask, gw, 0); // cli warning intentionally omitted RcpStaticRoute *rt = shm_find_route_static(ip, mask, gw); if (rt != NULL) rt->valid = 0; return 0; }
static void initializeDocForPosdb(XmlDoc *xmlDoc, const char *url, char *content) { CollectionRec *cr = g_collectiondb.getRec(static_cast<collnum_t >(0)); xmlDoc->setCollNum(cr->m_coll); xmlDoc->setFirstUrl(url); xmlDoc->m_oldDocValid = true; xmlDoc->m_oldDoc = NULL; xmlDoc->m_docIdValid = true; xmlDoc->m_docId = Titledb::getProbableDocId(url); xmlDoc->m_ipValid = true; xmlDoc->m_ip = atoip("127.0.0.2"); xmlDoc->m_useFakeMime = true; xmlDoc->m_httpReplyValid = true; xmlDoc->m_httpReplyAllocSize = strlen(content) + 1; xmlDoc->m_httpReplySize = xmlDoc->m_httpReplyAllocSize; xmlDoc->m_httpReply = static_cast<char*>(mmalloc(xmlDoc->m_httpReplyAllocSize, "httprep")); memcpy(xmlDoc->m_httpReply, content, xmlDoc->m_httpReplyAllocSize); xmlDoc->m_downloadStatusValid = true; xmlDoc->m_downloadStatus = 0; xmlDoc->m_useRobotsTxt = false; xmlDoc->m_useClusterdb = false; xmlDoc->m_useLinkdb = false; xmlDoc->m_useSpiderdb = false; xmlDoc->m_useTitledb = false; xmlDoc->m_useTagdb = false; xmlDoc->m_linkInfo1Valid = true; xmlDoc->ptr_linkInfo1 = NULL; xmlDoc->m_siteValid = true; xmlDoc->ptr_site = const_cast<char*>(url); xmlDoc->m_tagRecValid = true; xmlDoc->m_siteNumInlinksValid = true; xmlDoc->m_siteNumInlinks = 0; xmlDoc->m_sreqValid = true; xmlDoc->m_sreq.setFromInject(url); xmlDoc->m_versionValid = true; xmlDoc->m_version = TITLEREC_CURRENT_VERSION; // debug info xmlDoc->m_storeTermListInfo = true; }
int main(int argc, char **argv) { uint32_t ip; if(atoip(argv[1], &ip)) { printf("Invalid IP address\n"); return -1; } uint8_t mac[6]; if (atomac(mac, argv[2])) { printf("Invalid mac address\n"); return -1; } if(kernel_set_arp(ip, mac)) { printf("Arp entry not active\n"); } return 0; }
int main (int argc, char *argv[]) { acl *a; unsigned long addr; acl_contact *c = NULL; if (argc < 2) return usage(argv[0]); addr = atoip (argv[1]); if (! addr) return 0; acl_init (); load_config ("/etc/n2/n2rxd.conf"); a = acl_match (addr); if (! a) return 0; c = acl_get_contacts (a); while (c) { printf ("%s\n", c->contacturl); c = c->next; } return 0; }
// no ip name-server command; maximum two name servers are permitted int cliNoIpNameServerCmd(CliMode mode, int argc, char **argv) { ASSERT(strlen(argv[1]) <= CLI_MAX_HOSTNAME); char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // cleaning the return string // extract the ip address uint32_t addr; if (atoip(argv[3], &addr)) { sprintf(data, "Error: invalid IP address\n"); return RCPERR; } // update shared memory if (shm->config.name_server1 == addr) shm->config.name_server1 = 0; if (shm->config.name_server2 == addr) shm->config.name_server2 = 0; // change in system files needed update_resolvconf_file = 1; return 0; }
// ip name-server command; maximum two name servers are permitted int cliIpNameServerCmd(CliMode mode, int argc, char **argv) { ASSERT(strlen(argv[1]) <= CLI_MAX_HOSTNAME); char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // cleaning the return string // extract the ip address uint32_t addr; if (atoip(argv[2], &addr)) { sprintf(data, "Error: invalid IP address\n"); return RCPERR; } // nothing to do if the server is already configured if (shm->config.name_server1 == addr || shm->config.name_server2 == addr ) return RCPERR; // update shared memory if (shm->config.name_server1 == 0) { shm->config.name_server1 = addr; rcpDebug("services: updated name_server1\n"); // change in system files needed update_resolvconf_file = 1; return 0; } // in case we got here, just overwrite the second name server shm->config.name_server2 = addr; rcpDebug("services: updated name_server2\n"); // change in system files needed update_resolvconf_file = 1; return 0; }
// ip host command int cliIpHostNameCmd(CliMode mode, int argc, char **argv) { ASSERT(strlen(argv[1]) <= CLI_MAX_HOSTNAME); char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // cleaning the return string // extract the ip address uint32_t addr; if (atoip(argv[3], &addr)) { sprintf(data, "Error: invalid IP address\n"); return RCPERR; } // find the host RcpIpHost *found = host_find(argv[2]); // update or add a new host if (found) { // update the ip address found->ip = addr; } else { // add a new host RcpIpHost *newhost = host_find_empty(); memset(newhost, 0, sizeof(RcpIpHost)); strcpy(newhost->name, argv[2]); newhost->ip = addr; newhost->valid = 1; } // change in system files needed update_hosts_file = 1; // send dns update message to dns proxy trigger_dns_update(); return 0; }
u_char * var_ipfwacc(struct variable *vp, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { *write_method = 0; /* assume it isnt writable for the time being */ *var_len = sizeof(ret_val); /* assume an integer and change later if not */ if (header_simple_table(vp,name,length,exact,var_len,write_method,readrule(0))) return (NULL); if (readrule(name[*length-1])){ /* this is where we do the value assignments for the mib results. */ switch(vp->magic) { case IPFWACCINDEX: ret_val = name[*length-1]; return((u_char *) (&ret_val)); case IPFWACCSRCADDR: atoip(0); return((u_char *) (&ret_val)); case IPFWACCSRCNM: atoip(9); return((u_char *) (&ret_val)); case IPFWACCDSTADDR: atoip(19); return((u_char *) (&ret_val)); case IPFWACCDSTNM: atoip(28); return((u_char *) (&ret_val)); case IPFWACCVIANAME: { int i=37; /* position in the rule */ while (rule[i]!=' '&&i<IPFWRULELEN-1) i++; rule[i]=0; return (rule+37); } case IPFWACCVIAADDR: { int i=37; /* position in the rule */ while (rule[i]!=' '&&i<IPFWRULELEN-9) i++; atoip(i+1); return((u_char *) (&ret_val)); } case IPFWACCPROTO: switch (getflags()&IP_FW_F_KIND){ case IP_FW_F_ALL: ret_val=2; return ((u_char *) (&ret_val)); case IP_FW_F_TCP: ret_val=3; return ((u_char *) (&ret_val)); case IP_FW_F_UDP: ret_val=4; return ((u_char *) (&ret_val)); case IP_FW_F_ICMP: ret_val=5; return ((u_char *) (&ret_val)); default: ret_val=1; return((u_char *) (&ret_val)); } case IPFWACCBIDIR: ret_val=((getflags()&IP_FW_F_BIDIR)?2:1); return ((u_char *) (&ret_val)); case IPFWACCDIR: ret_val=(getflags()&(IP_FW_F_ACCTIN|IP_FW_F_ACCTOUT)); if (ret_val==IP_FW_F_ACCTIN) ret_val=2; else if (ret_val==IP_FW_F_ACCTOUT) ret_val=3; else ret_val=1; return ((u_char *) (&ret_val)); case IPFWACCBYTES: getnumeric(4); return ((u_char *) (&ret_val)); case IPFWACCPACKETS: getnumeric(3); return ((u_char *) (&ret_val)); case IPFWACCNSRCPRTS: getnumeric(1); return ((u_char *) (&ret_val)); case IPFWACCNDSTPRTS: getnumeric(2); return ((u_char *) (&ret_val)); case IPFWACCSRCISRNG: ret_val=((getflags()&IP_FW_F_SRNG)?1:2); return ((u_char *) (&ret_val)); case IPFWACCDSTISRNG: ret_val=((getflags()&IP_FW_F_DRNG)?1:2); return ((u_char *) (&ret_val)); case IPFWACCPORT1: case IPFWACCPORT2: case IPFWACCPORT3: case IPFWACCPORT4: case IPFWACCPORT5: case IPFWACCPORT6: case IPFWACCPORT7: case IPFWACCPORT8: case IPFWACCPORT9: case IPFWACCPORT10: getnumeric(5+(vp->magic)-IPFWACCPORT1); return ((u_char *) (&ret_val)); } } return NULL; }
void Conf::setRootIps ( ) { //m_numDns = 16; //for ( int32_t i = 0; i < m_numDns; i++ ) // m_dnsPorts[i] = 53; //m_numDns = 0; // set m_numDns based on Conf::m_dnsIps[] array int32_t i; for ( i = 0; i < 16 ; i++ ) { m_dnsPorts[i] = 53; if ( ! g_conf.m_dnsIps[i] ) break; } m_numDns = i; // hardcode google for now... //m_dnsIps[0] = atoip("8.8.8.8",7); //m_dnsIps[1] = atoip("8.8.4.4",7); //m_numDns = 2; Host *h = g_hostdb.getMyHost(); //char *ipStr = "10.5.0.3"; //char *ipStr = "10.5.56.78"; // gk268 now on roadrunner //char *ipStr = "10.5.56.77"; // gk267 now cnsp-routed bind9 server // now sp1 for speed (quad processor) //char *ipStr = "10.5.66.11"; // fail back to google public dns char *ipStr = "8.8.8.8"; // try google first dibs. NO! they are unresponsive after a while //char *ipStr = "8.8.4.4"; // for some reason scproxy2 local bind9 not responding to us!!! fix! //if ( h->m_type & HT_SCPROXY ) ipStr = "127.0.0.1"; //if ( h->m_type & HT_PROXY ) ipStr = "127.0.0.1"; if ( h->m_type & HT_SCPROXY ) ipStr = "8.8.8.8"; if ( h->m_type & HT_PROXY ) ipStr = "8.8.8.8"; // if we are a proxy, notably a spider compression proxy... //if ( g_proxy.isProxy() ) ipStr = "127.0.0.1"; if ( m_numDns == 0 ) { m_dnsIps[0] = atoip( ipStr , gbstrlen(ipStr) ); m_dnsPorts[0] = 53; m_numDns = 1; } // default this to off on startup for now until it works better m_askRootNameservers = false; // and return as well return; char *rootIps[] = { "192.228.79.201", "192.33.4.12", "128.8.10.90", //"192.203.230.10", ping timedout "192.5.5.241", //"192.112.36.4", ping timedout //"128.63.2.53", ping timedout //"192.36.148.17", "192.58.128.30", "193.0.14.129", //"198.32.64.12", "199.7.83.42", // new guy "202.12.27.33", "198.41.0.4" }; int32_t n = sizeof(rootIps)/sizeof(char *); if ( n > MAX_RNSIPS ) { log("admin: Too many root nameserver ips. Truncating."); n = MAX_RNSIPS; } m_numRns = n; for ( int32_t i = 0 ; i < n ; i++ ) { m_rnsIps [i] = atoip(rootIps[i],gbstrlen(rootIps[i])); m_rnsPorts[i] = 53; log(LOG_INIT,"dns: Using root nameserver #%"INT32" %s.", i,iptoa(m_rnsIps[i])); } }
int main (int argc, char *argv[]) { unsigned long ipaddr; netload_rec **rec; netload_info inf; unsigned int dt; unsigned int addr; int offs; int search; const char *pat; unsigned int intpat; const char *field; int matches; int mincpu; int i; struct tm *ltm; time_t ti; /* n2pgrep <date> <user|pid|name> <string> */ if (argc<5) { fprintf (stderr, "%% Usage: %s <addr> <date> user|pid|name <word>" " [mincpu <percentage>]\n" " <date> := YYYYMMDD | today | yesterday\n", argv[0]); return 1; } addr = atoip (argv[1]); if (! addr) { fprintf (stderr, "%% Illegal host description.\n"); return 1; } dt = strtoul (argv[2], NULL, 10); if (! dt) { if (! strcmp (argv[2], "today")) { ti = time (NULL); } else if (! strcmp (argv[2], "yesterday")) { ti = time (NULL) - 86400; } else { fprintf (stderr, "%% Invalid date spec: %s\n", argv[2]); return 1; } ltm = localtime (&ti); dt = (10000 * (ltm->tm_year+1900)) + (100 * (ltm->tm_mon+1)) + ltm->tm_mday; } pat = argv[4]; intpat = strtoul (pat, NULL, 10); mincpu = 0; if (! strcmp (argv[3], "user")) search = SEARCH_USER; else if (! strcmp (argv[3], "pid")) search = SEARCH_PID; else if (! strcmp (argv[3], "name")) search = SEARCH_NAME; else { fprintf (stderr, "%% Error in field argument\n"); return 1; } if (argc>6) { if (strcmp (argv[5], "mincpu")) { fprintf (stderr, "%% Unrecognized option '%s'\n", argv[5]); return 1; } mincpu = 100 * atoi (argv[6]); } rec = diskdb_get_range (addr, dt, 0, 1439); for (offs=0; offs<1440; ++offs) { if (rec[offs] && decode_rec_inline (rec[offs], &inf)) { for (i=0; i<inf.ntop; ++i) { matches = 0; switch (search) { case SEARCH_USER: field = inf.tprocs[i].username; if (strstr (field, pat)) matches = 1; break; case SEARCH_PID: if (intpat == inf.tprocs[i].pid) matches = 1; break; case SEARCH_NAME: field = inf.tprocs[i].ptitle; if (strstr (field, pat)) matches = 1; break; } if (matches && (inf.tprocs[i].pcpu >= mincpu)) { printf ("%2i:%02i ", offs/60, offs % 60); printf ("%7u %-9s %5.2f %s\n", inf.tprocs[i].pid, inf.tprocs[i].username, (double) inf.tprocs[i].pcpu / 100.0, inf.tprocs[i].ptitle); } } } } }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno, const char *fname) { EUID_ASSERT(); // check ignore list int i; for (i = 0; i < MAX_PROFILE_IGNORE; i++) { if (cfg.profile_ignore[i] == NULL) break; if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0) return 0; // ignore line } if (strncmp(ptr, "ignore ", 7) == 0) { char *str = strdup(ptr + 7); if (*str == '\0') { fprintf(stderr, "Error: invalid ignore option\n"); exit(1); } // find an empty entry in profile_ignore array int j; for (j = 0; j < MAX_PROFILE_IGNORE; j++) { if (cfg.profile_ignore[j] == NULL) break; } if (j >= MAX_PROFILE_IGNORE) { fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); exit(1); } // ... and configure it else cfg.profile_ignore[j] = str; return 0; } // mkdir if (strncmp(ptr, "mkdir ", 6) == 0) { fs_mkdir(ptr + 6); return 1; // process mkdir again while applying blacklists } // mkfile if (strncmp(ptr, "mkfile ", 7) == 0) { fs_mkfile(ptr + 7); return 1; // process mkfile again while applying blacklists } // sandbox name else if (strncmp(ptr, "name ", 5) == 0) { cfg.name = ptr + 5; if (strlen(cfg.name) == 0) { fprintf(stderr, "Error: invalid sandbox name\n"); exit(1); } return 0; } else if (strcmp(ptr, "ipc-namespace") == 0) { arg_ipc = 1; return 0; } // seccomp, caps, private, user namespace else if (strcmp(ptr, "noroot") == 0) { #if HAVE_USERNS if (checkcfg(CFG_USERNS)) check_user_namespace(); else warning_feature_disabled("noroot"); #endif return 0; } else if (strcmp(ptr, "nonewprivs") == 0) { arg_nonewprivs = 1; return 0; } else if (strcmp(ptr, "seccomp") == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) arg_seccomp = 1; else warning_feature_disabled("seccomp"); #endif return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps_default_filter = 1; return 0; } else if (strcmp(ptr, "caps.drop all") == 0) { arg_caps_drop_all = 1; return 0; } else if (strcmp(ptr, "shell none") == 0) { arg_shell_none = 1; return 0; } else if (strcmp(ptr, "tracelog") == 0) { arg_tracelog = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } if (strncmp(ptr, "private-home ", 13) == 0) { #ifdef HAVE_PRIVATE_HOME if (checkcfg(CFG_PRIVATE_HOME)) { if (cfg.home_private_keep) { if ( asprintf(&cfg.home_private_keep, "%s,%s", cfg.home_private_keep, ptr + 13) < 0 ) errExit("asprintf"); } else cfg.home_private_keep = ptr + 13; arg_private = 1; } else warning_feature_disabled("private-home"); #endif return 0; } else if (strcmp(ptr, "allusers") == 0) { arg_allusers = 1; return 0; } else if (strcmp(ptr, "private-dev") == 0) { arg_private_dev = 1; return 0; } else if (strcmp(ptr, "private-tmp") == 0) { arg_private_tmp = 1; return 0; } else if (strcmp(ptr, "nogroups") == 0) { arg_nogroups = 1; return 0; } else if (strcmp(ptr, "nosound") == 0) { arg_nosound = 1; return 0; } else if (strcmp(ptr, "novideo") == 0) { arg_novideo = 1; return 0; } else if (strcmp(ptr, "no3d") == 0) { arg_no3d = 1; return 0; } else if (strcmp(ptr, "allow-private-blacklist") == 0) { arg_allow_private_blacklist = 1; return 0; } else if (strcmp(ptr, "netfilter") == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) arg_netfilter = 1; else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "netfilter ", 10) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netfilter = 1; arg_netfilter_file = strdup(ptr + 10); if (!arg_netfilter_file) errExit("strdup"); check_netfilter_file(arg_netfilter_file); } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "netfilter6 ", 11) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netfilter6 = 1; arg_netfilter6_file = strdup(ptr + 11); if (!arg_netfilter6_file) errExit("strdup"); check_netfilter_file(arg_netfilter6_file); } else warning_feature_disabled("networking"); #endif return 0; } else if (strcmp(ptr, "net none") == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_nonetwork = 1; cfg.bridge0.configured = 0; cfg.bridge1.configured = 0; cfg.bridge2.configured = 0; cfg.bridge3.configured = 0; cfg.interface0.configured = 0; cfg.interface1.configured = 0; cfg.interface2.configured = 0; cfg.interface3.configured = 0; } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "net ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { #ifdef HAVE_NETWORK_RESTRICTED // compile time restricted networking if (getuid() != 0) { fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); exit(1); } #endif // run time restricted networking if (checkcfg(CFG_RESTRICTED_NETWORK) && getuid() != 0) { fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); exit(1); } if (strcmp(ptr + 4, "lo") == 0) { fprintf(stderr, "Error: cannot attach to lo device\n"); exit(1); } Bridge *br; if (cfg.bridge0.configured == 0) br = &cfg.bridge0; else if (cfg.bridge1.configured == 0) br = &cfg.bridge1; else if (cfg.bridge2.configured == 0) br = &cfg.bridge2; else if (cfg.bridge3.configured == 0) br = &cfg.bridge3; else { fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); exit(1); } net_configure_bridge(br, ptr + 4); } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "veth-name ", 10) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } br->veth_name = strdup(ptr + 10); if (br->veth_name == NULL) errExit("strdup"); if (*br->veth_name == '\0') { fprintf(stderr, "Error: no veth-name configured\n"); exit(1); } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "iprange ", 8) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->iprange_start || br->iprange_end) { fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n"); exit(1); } // parse option arguments char *firstip = ptr + 8; char *secondip = firstip; while (*secondip != '\0') { if (*secondip == ',') break; secondip++; } if (*secondip == '\0') { fprintf(stderr, "Error: invalid IP range\n"); exit(1); } *secondip = '\0'; secondip++; // check addresses if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || br->iprange_start >= br->iprange_end) { fprintf(stderr, "Error: invalid IP range\n"); exit(1); } if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) { fprintf(stderr, "Error: IP range addresses not in network range\n"); exit(1); } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "mac ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (mac_not_zero(br->macsandbox)) { fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); exit(1); } // read the address if (atomac(ptr + 4, br->macsandbox)) { fprintf(stderr, "Error: invalid MAC address\n"); exit(1); } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "mtu ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { fprintf(stderr, "Error: invalid mtu value\n"); exit(1); } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "ip ", 3) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->arg_ip_none || br->ipsandbox) { fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); exit(1); } // configure this IP address for the last bridge defined if (strcmp(ptr + 3, "none") == 0) br->arg_ip_none = 1; else { if (atoip(ptr + 3, &br->ipsandbox)) { fprintf(stderr, "Error: invalid IP address\n"); exit(1); } } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "ip6 ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->arg_ip_none || br->ip6sandbox) { fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); exit(1); } // configure this IP address for the last bridge defined // todo: verify ipv6 syntax br->ip6sandbox = ptr + 4; // if (atoip(argv[i] + 5, &br->ipsandbox)) { // fprintf(stderr, "Error: invalid IP address\n"); // exit(1); // } } else warning_feature_disabled("networking"); #endif return 0; } else if (strncmp(ptr, "defaultgw ", 10) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { if (atoip(ptr + 10, &cfg.defaultgw)) { fprintf(stderr, "Error: invalid IP address\n"); exit(1); } } else warning_feature_disabled("networking"); #endif return 0; } if (strcmp(ptr, "apparmor") == 0) { #ifdef HAVE_APPARMOR arg_apparmor = 1; #endif return 0; } if (strncmp(ptr, "protocol ", 9) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { if (cfg.protocol) { fwarning("a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9); return 0; } // store list cfg.protocol = strdup(ptr + 9); if (!cfg.protocol) errExit("strdup"); } else warning_feature_disabled("seccomp"); #endif return 0; } if (strncmp(ptr, "env ", 4) == 0) { env_store(ptr + 4, SETENV); return 0; } if (strncmp(ptr, "rmenv ", 6) == 0) { env_store(ptr + 6, RMENV); return 0; } // seccomp drop list on top of default list if (strncmp(ptr, "seccomp ", 8) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list = seccomp_check_list(ptr + 8); } else if (!arg_quiet) warning_feature_disabled("seccomp"); #endif return 0; } // seccomp drop list without default list if (strncmp(ptr, "seccomp.drop ", 13) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list_drop = seccomp_check_list(ptr + 13); } else warning_feature_disabled("seccomp"); #endif return 0; } // seccomp keep list if (strncmp(ptr, "seccomp.keep ", 13) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list_keep= seccomp_check_list(ptr + 13); } else warning_feature_disabled("seccomp"); #endif return 0; } // caps drop list if (strncmp(ptr, "caps.drop ", 10) == 0) { arg_caps_drop = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify caps list and exit if problems caps_check_list(arg_caps_list, NULL); return 0; } // caps keep list if (strncmp(ptr, "caps.keep ", 10) == 0) { arg_caps_keep = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify caps list and exit if problems caps_check_list(arg_caps_list, NULL); return 0; } // hostname if (strncmp(ptr, "hostname ", 9) == 0) { cfg.hostname = ptr + 9; return 0; } // hosts-file if (strncmp(ptr, "hosts-file ", 11) == 0) { cfg.hosts_file = fs_check_hosts_file(ptr + 11); return 0; } // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; if (atoip(ptr + 4, &dns)) { fprintf(stderr, "Error: invalid DNS server IP address\n"); return 1; } if (cfg.dns1 == 0) cfg.dns1 = dns; else if (cfg.dns2 == 0) cfg.dns2 = dns; else if (cfg.dns3 == 0) cfg.dns3 = dns; else { fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); return 1; } return 0; } // cpu affinity if (strncmp(ptr, "cpu ", 4) == 0) { read_cpu_list(ptr + 4); return 0; } // nice value if (strncmp(ptr, "nice ", 4) == 0) { cfg.nice = atoi(ptr + 5); if (getuid() != 0 &&cfg.nice < 0) cfg.nice = 0; arg_nice = 1; return 0; } // cgroup if (strncmp(ptr, "cgroup ", 7) == 0) { set_cgroup(ptr + 7); return 0; } // writable-etc if (strcmp(ptr, "writable-etc") == 0) { if (cfg.etc_private_keep) { fprintf(stderr, "Error: private-etc and writable-etc are mutually exclusive\n"); exit(1); } arg_writable_etc = 1; return 0; } if (strcmp(ptr, "machine-id") == 0) { arg_machineid = 1; return 0; } // writable-var if (strcmp(ptr, "writable-var") == 0) { arg_writable_var = 1; return 0; } if (strcmp(ptr, "writable-var-log") == 0) { arg_writable_var_log = 1; return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; fs_check_private_dir(); arg_private = 1; return 0; } if (strcmp(ptr, "x11 none") == 0) { arg_x11_block = 1; return 0; } if (strcmp(ptr, "x11 xephyr") == 0) { #ifdef HAVE_X11 if (checkcfg(CFG_X11)) { char *x11env = getenv("FIREJAIL_X11"); if (x11env && strcmp(x11env, "yes") == 0) { return 0; } else { // start x11 x11_start_xephyr(cfg.original_argc, cfg.original_argv); exit(0); } } else warning_feature_disabled("x11"); #endif return 0; } if (strcmp(ptr, "x11 xorg") == 0) { #ifdef HAVE_X11 if (checkcfg(CFG_X11)) arg_x11_xorg = 1; else warning_feature_disabled("x11"); #endif return 0; } if (strcmp(ptr, "x11 xpra") == 0) { #ifdef HAVE_X11 if (checkcfg(CFG_X11)) { char *x11env = getenv("FIREJAIL_X11"); if (x11env && strcmp(x11env, "yes") == 0) { return 0; } else { // start x11 x11_start_xpra(cfg.original_argc, cfg.original_argv); exit(0); } } else warning_feature_disabled("x11"); #endif return 0; } if (strcmp(ptr, "x11 xvfb") == 0) { #ifdef HAVE_X11 if (checkcfg(CFG_X11)) { char *x11env = getenv("FIREJAIL_X11"); if (x11env && strcmp(x11env, "yes") == 0) { return 0; } else { // start x11 x11_start_xvfb(cfg.original_argc, cfg.original_argv); exit(0); } } else warning_feature_disabled("x11"); #endif return 0; } if (strcmp(ptr, "x11") == 0) { #ifdef HAVE_X11 if (checkcfg(CFG_X11)) { char *x11env = getenv("FIREJAIL_X11"); if (x11env && strcmp(x11env, "yes") == 0) { return 0; } else { // start x11 x11_start(cfg.original_argc, cfg.original_argv); exit(0); } } else warning_feature_disabled("x11"); #endif return 0; } // private /etc list of files and directories if (strncmp(ptr, "private-etc ", 12) == 0) { if (arg_writable_etc) { fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n"); exit(1); } if (cfg.etc_private_keep) { if ( asprintf(&cfg.etc_private_keep, "%s,%s", cfg.etc_private_keep, ptr + 12) < 0 ) errExit("asprintf"); } else { cfg.etc_private_keep = ptr + 12; } arg_private_etc = 1; return 0; } // private /opt list of files and directories if (strncmp(ptr, "private-opt ", 12) == 0) { if (cfg.opt_private_keep) { if ( asprintf(&cfg.opt_private_keep, "%s,%s", cfg.opt_private_keep, ptr + 12) < 0 ) errExit("asprintf"); } else { cfg.opt_private_keep = ptr + 12; } arg_private_opt = 1; return 0; } // private /srv list of files and directories if (strncmp(ptr, "private-srv ", 12) == 0) { if (cfg.srv_private_keep) { if ( asprintf(&cfg.srv_private_keep, "%s,%s", cfg.srv_private_keep, ptr + 12) < 0 ) errExit("asprintf"); } else { cfg.srv_private_keep = ptr + 12; } arg_private_srv = 1; return 0; } // private /bin list of files if (strncmp(ptr, "private-bin ", 12) == 0) { if (cfg.bin_private_keep) { if ( asprintf(&cfg.bin_private_keep, "%s,%s", cfg.bin_private_keep, ptr + 12) < 0 ) errExit("asprintf"); } else { cfg.bin_private_keep = ptr + 12; } arg_private_bin = 1; return 0; } #ifdef HAVE_OVERLAYFS if (strncmp(ptr, "overlay-named ", 14) == 0) { if (checkcfg(CFG_OVERLAYFS)) { if (cfg.chrootdir) { fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); exit(1); } struct stat s; if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); exit(1); } arg_overlay = 1; arg_overlay_keep = 1; arg_overlay_reuse = 1; char *subdirname = ptr + 14; if (subdirname == '\0') { fprintf(stderr, "Error: invalid overlay option\n"); exit(1); } // check name invalid_filename(subdirname); if (strstr(subdirname, "..") || strstr(subdirname, "/")) { fprintf(stderr, "Error: invalid overlay name\n"); exit(1); } cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse); } return 0; } else if (strcmp(ptr, "overlay-tmpfs") == 0) { if (checkcfg(CFG_OVERLAYFS)) { if (cfg.chrootdir) { fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); exit(1); } struct stat s; if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); exit(1); } arg_overlay = 1; return 0; } } else if (strcmp(ptr, "overlay") == 0) { if (checkcfg(CFG_OVERLAYFS)) { if (cfg.chrootdir) { fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); exit(1); } struct stat s; if (stat("/proc/sys/kernel/grsecurity", &s) == 0) { fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n"); exit(1); } arg_overlay = 1; arg_overlay_keep = 1; char *subdirname; if (asprintf(&subdirname, "%d", getpid()) == -1) errExit("asprintf"); cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse); free(subdirname); return 0; } } #endif // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { #ifdef HAVE_BIND if (checkcfg(CFG_BIND)) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: missing second directory for bind\n"); exit(1); } // check directories invalid_filename(dname1); invalid_filename(dname2); if (strstr(dname1, "..") || strstr(dname2, "..")) { fprintf(stderr, "Error: invalid file name.\n"); exit(1); } if (is_link(dname1) || is_link(dname2)) { fprintf(stderr, "Symbolic links are not allowed for bind command\n"); exit(1); } // insert comma back *(dname2 - 1) = ','; return 1; } else warning_feature_disabled("bind"); #endif return 0; } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { check_unsigned(ptr + 14, "Error: invalid rlimit in profile file: "); sscanf(ptr + 14, "%llu", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { check_unsigned(ptr + 13, "Error: invalid rlimit in profile file: "); sscanf(ptr + 13, "%llu", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { check_unsigned(ptr + 13, "Error: invalid rlimit in profile file: "); sscanf(ptr + 13, "%llu", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { check_unsigned(ptr + 18, "Error: invalid rlimit in profile file: "); sscanf(ptr + 18, "%llu", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } if (strncmp(ptr, "join-or-start ", 14) == 0) { // try to join by name only pid_t pid; if (!name2pid(ptr + 14, &pid)) { if (!cfg.shell && !arg_shell_none) cfg.shell = guess_shell(); // find first non-option arg int i; for (i = 1; i < cfg.original_argc && strncmp(cfg.original_argv[i], "--", 2) != 0; i++); join(pid, cfg.original_argc,cfg.original_argv, i + 1); exit(0); } // set sandbox name and start normally cfg.name = ptr + 14; if (strlen(cfg.name) == 0) { fprintf(stderr, "Error: invalid sandbox name\n"); exit(1); } return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "blacklist-nolog ", 16) == 0) ptr += 16; else if (strncmp(ptr, "noblacklist ", 12) == 0) ptr += 12; else if (strncmp(ptr, "whitelist ", 10) == 0) { #ifdef HAVE_WHITELIST if (checkcfg(CFG_WHITELIST)) { arg_whitelist = 1; ptr += 10; } else return 0; #else return 0; #endif } else if (strncmp(ptr, "nowhitelist ", 12) == 0) ptr += 12; else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "read-write ", 11) == 0) ptr += 11; else if (strncmp(ptr, "noexec ", 7) == 0) ptr += 7; else if (strncmp(ptr, "tmpfs ", 6) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n"); exit(1); } ptr += 6; } else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else if (fname != NULL) fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames invalid_filename(ptr); if (strstr(ptr, "..")) { if (lineno == 0) fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); else if (fname != NULL) fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } return 1; }
void http_settings(char *rx, unsigned int rx_len) { unsigned int item, found, len; int i; char buf[16]; MAC_Addr mac; IP_Addr ip; unsigned int rgb; for(; rx_len!=0;) { len = strlen("restartwebradio="); if(strncmpi(rx, "restartwebradio=", len) == 0) { rx += len; rx_len -= len; cpu_reset(); } for(item=0, found=0; item<SETTINGSITEMS; item++) { if(settingsmenu[item].ini[0] == 0) { continue; } len = sprintf(buf, "%s=", settingsmenu[item].ini); if(strncmpi(rx, buf, len) == 0) { rx += len; rx_len -= len; len = url_decode(rx, rx, rx_len); i = 0; switch(settingsmenu[item].format) { case F_NR: //p1-p2, p3=step size i = atoi(rx); if(i < settingsmenu[item].p1){ i = settingsmenu[item].p1; } else if(i > settingsmenu[item].p2){ i = settingsmenu[item].p2; } itoa(i, buf, 10); ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf); if(settingsmenu[item].set){ settingsmenu[item].set((void*)(int)i); } break; case F_OR: //p1 or p2 i = atoi(rx); if((i != settingsmenu[item].p1) && (i != settingsmenu[item].p2)){ i = settingsmenu[item].p1; } itoa(i, buf, 10); ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf); if(settingsmenu[item].set){ settingsmenu[item].set((void*)(int)i); } break; case F_STR: //p1=max len if((settingsmenu[item].p1 != 0) && (strlen(rx) > (unsigned)settingsmenu[item].p1)) { rx[settingsmenu[item].p1] = 0; } ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, rx); if(settingsmenu[item].set){ settingsmenu[item].set(rx); } break; case F_MAC: mac = atomac(rx); ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, mactoa(mac)); //if(settingsmenu[item].set){ settingsmenu[item].set((void*)(MAC_Addr)mac); } break; case F_IP: ip = atoip(rx); ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, iptoa(ip)); if(settingsmenu[item].set){ settingsmenu[item].set((void*)(IP_Addr)atoip(rx)); } break; case F_RGB: rgb = atorgb(rx); sprintf(buf, "%03i,%03i,%03i", GET_RED(rgb), GET_GREEN(rgb), GET_BLUE(rgb)); ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf); if(settingsmenu[item].set){ settingsmenu[item].set((void*)(unsigned int)rgb); } break; } rx += len; rx_len -= len; found = 1; break; } } if(found == 0) { rx++; rx_len--; } } menu_drawwnd(1); return; }
bool GetPrivateUserAndIpData() { // Find parameters line. GetPostParameterLine(); if (_requestLine[0] == CH_NONE) { return false; } // Process params. char * paramVal; uint8_t paramLen; uint8_t ipBuff[IP_LEN]; bool findParam; bool cnvResult; for (uint8_t col = 0; col < VALID_USER_AND_IP_LEN; col++) { ValidationData& vd = ValidUserAndIP[col]; switch (col) { // User name. case 0: { // cbX=1. findParam = FindParameter(_requestLine, PREFF_US, CH_1, paramVal, paramLen); vd.IsValid = (findParam && paramLen >= 3 && paramLen <= 8) ? true : false; vd.Value = paramVal; vd.Length = paramLen; if (vd.IsValid) { strNCopy(DeviceDataUserAndIP.User, paramVal, paramLen); } } break; // Password. case 1: { // cbX=1. findParam = FindParameter(_requestLine, PREFF_PS, CH_1, paramVal, paramLen); vd.IsValid = (findParam && paramLen >= 3 && paramLen <= 8) ? true : false; vd.Value = paramVal; vd.Length = paramLen; if (vd.IsValid) { strNCopy(DeviceDataUserAndIP.Password, paramVal, paramLen); } } break; // IP. case 2: { findParam = FindParameter(_requestLine, PREFF_IP, CH_1, paramVal, paramLen); cnvResult = atoip(paramVal, ipBuff); vd.IsValid = findParam && cnvResult ? 1 : 0; vd.Value = paramVal; vd.Length = paramLen; if (cnvResult) { memcpy(DeviceDataUserAndIP.IP, ipBuff, IP_LEN); } } break; // Subnet mask. case 3: { findParam = FindParameter(_requestLine, PREFF_SN, CH_1, paramVal, paramLen); cnvResult = atoip(paramVal, ipBuff); vd.IsValid = findParam && cnvResult ? 1 : 0; vd.Value = paramVal; vd.Length = paramLen; if (cnvResult) { memcpy(DeviceDataUserAndIP.SubnetMask, ipBuff, IP_LEN); } } break; // Subnet mask. case 4: { findParam = FindParameter(_requestLine, PREFF_GW, CH_1, paramVal, paramLen); cnvResult = atoip(paramVal, ipBuff); vd.IsValid = findParam && cnvResult ? 1 : 0; vd.Value = paramVal; vd.Length = paramLen; if (cnvResult) { memcpy(DeviceDataUserAndIP.Gateway, ipBuff, IP_LEN); } } break; } } return true; }
// . when the Conf::m_proxyIps parm is updated we call this to rebuild // s_iptab, our table of SpiderProxy instances, which has the proxies and // their performance statistics. // . we try to maintain stats of ip/ports that did NOT change when rebuilding. bool buildProxyTable ( ) { // scan the NEW list of proxy ip/port pairs in g_conf char *p = g_conf.m_proxyIps.getBufStart(); HashTableX tmptab; tmptab.set(8,0,16,NULL,0,false,"tmptab"); // scan the user inputted space-separated list of ip:ports // (optional username:password@ip:port) for ( ; *p ; ) { // skip white space if ( is_wspace_a(*p) ) { p++; continue; } // skip http:// if ( strncasecmp(p,"http://",7) == 0 ) { p += 7; continue; } // scan in an ip:port char *s = p; char *portStr = NULL; int32_t dc = 0, pc = 0, gc = 0, bc = 0; const char *msg; char *usernamePwd = NULL; int32_t usernamePwdLen = 0; char *ipStart = p; // scan all characters until we hit \0 or another whitespace for ( ; *s && !is_wspace_a(*s); s++) { if ( *s == '@' ) { // must be username:pwd if ( pc != 1 ) { msg = "bad username:password"; goto hadError; } usernamePwd = p; usernamePwdLen = s - p; if ( usernamePwdLen >= MAXUSERNAMEPWD-2 ) { msg = "username:password too long"; goto hadError; } dc = 0; gc = 0; bc = 0; pc = 0; portStr = NULL; ipStart = s+1; continue; } if ( *s == '.' ) { dc++; continue; } if ( *s == ':' ) { portStr=s; pc++; continue; } if ( is_digit(*s) ) { gc++; continue; } bc++; continue; } // ensure it is a legit ip:port combo msg = NULL; if ( gc < 4 ) msg = "not enough digits for an ip"; if ( pc > 1 ) msg = "too many colons"; if ( dc != 3 ) msg = "need 3 dots for an ip address"; if ( bc ) msg = "got illegal char in ip:port listing"; if ( msg ) { hadError: char c = *s; *s = '\0'; log("buf: %s for %s",msg,p); *s = c; return false; } // convert it int32_t iplen = s - ipStart; if ( portStr ) iplen = portStr - ipStart; int32_t ip = atoip(ipStart,iplen); // another sanity check if ( ip == 0 || ip == -1 ) { log("spider: got bad proxy ip for %s",p); return false; } // and the port default is 80 int32_t port = 80; if ( portStr ) port = atol2(portStr+1,s-portStr-1); if ( port < 0 || port > 65535 ) { log("spider: got bad proxy port for %s",p); return false; } // . we got a legit ip:port // . see if already in our table uint64_t ipKey = (uint32_t)ip; ipKey <<= 16; ipKey |= (uint16_t)(port & 0xffff); // also store into tmptable to see what we need to remove tmptab.addKey(&ipKey); // see if in table int32_t islot = s_iptab.getSlot( &ipKey); // advance p p = s; // if in there, keep it as is if ( islot >= 0 ) continue; // otherwise add new entry SpiderProxy newThing; memset ( &newThing , 0 , sizeof(SpiderProxy)); newThing.m_ip = ip; newThing.m_port = port; newThing.m_lastDownloadTookMS = -1; newThing.m_lastSuccessfulTestMS = -1; gbmemcpy(newThing.m_usernamePwd,usernamePwd,usernamePwdLen); // ensure it is NULL terminated newThing.m_usernamePwd[usernamePwdLen] = '\0'; if ( ! s_iptab.addKey ( &ipKey, &newThing ) ) return false; } redo: int32_t removed = 0; // scan all SpiderProxies in tmptab for ( int32_t i = 0 ; i < s_iptab.getNumSlots() ; i++ ) { // skip empty buckets in hashtable s_iptab if ( ! s_iptab.m_flags[i] ) continue; // get the key int64_t key = *(int64_t *)s_iptab.getKeyFromSlot(i); // must also exist in tmptab, otherwise it got removed by user if ( tmptab.isInTable ( &key ) ) continue; // skip if not in table if ( s_iptab.getSlot ( &key ) < 0 ) { log("sproxy: iptable hashing messed up"); continue; } // shoot, it got removed. not in the new list of ip:ports s_iptab.removeKey ( &key ); removed++; // hashtable is messed up now, start over //goto redo; } if ( removed ) goto redo; return true; }
int main ( int argc , char *argv[] ) { // let's ensure our core file can dump struct rlimit lim; lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; if ( setrlimit(RLIMIT_CORE,&lim) ) log("blaster::setrlimit: %s", mstrerror(errno) ); //g_conf.m_maxMem = 500000000; // init our table for doing zobrist hashing if ( ! hashinit() ) { log("blaster::hashinit failed" ); return 1; } // init the memory class after conf since it gets maxMem from Conf //if ( ! g_mem.init ( 20000000 ) ) { // log("blaster::Mem init failed" ); return 1; } //g_mem.m_maxMem = 200000000; // start up log file if ( ! g_log.init( "/tmp/blasterLog" ) ) { log("blaster::Log open /tmp/blasterLog failed" ); return 1; } // get dns ip from /etc/resolv.conf g_conf.m_dnsIps[0] = 0; FILE *fd = fopen ( "/etc/resolv.conf" , "r" ); if ( ! fd ) { log("blaster::fopen: /etc/resolve.conf %s", mstrerror(errno)); return 1; } char tmp[1024]; while ( fgets ( tmp , 1024 , fd ) ) { // tmp buf ptr char *p = tmp; // skip comments if ( *p == '#' ) continue; // skip nameserver name if ( ! isdigit(*p) ) while ( ! isspace ( *p ) ) p++ ; // skip spaces while ( isspace ( *p ) ) p++; // if this is not a digit, continue if ( ! isdigit(*p) ) continue; // get ip g_conf.m_dnsIps[0] = atoip ( p , gbstrlen(p) ); // done break; } fclose ( fd ); // if no dns server found, bail if ( g_conf.m_dnsIps[0] == 0 ) { log("blaster:: no dns ip found in /etc/resolv.conf");return 1;} // hack # of dns servers g_conf.m_numDns = 1; g_conf.m_dnsPorts[0] = 53; //g_conf.m_dnsIps [0] = atoip ( "192.168.0.1", 11 ); //g_conf.m_dnsClientPort = 9909; g_conf.m_dnsMaxCacheMem = 1024*10; // hack http server port to -1 (none) //g_conf.m_httpPort = 0; g_conf.m_httpMaxSockets = 200; //g_conf.m_httpMaxReadBufSize = 102*1024*1024; g_conf.m_httpMaxSendBufSize = 16*1024; //g_conf.m_httpMaxDownloadSockets = 200; if ( argc != 4 && argc != 5 && argc !=6 ) { printUsage: fprintf(stderr,"USAGE: blaster [fileOfUrls | -r<num random words><server>] [maxNumThreads] [wait in ms] " "<lines to skip> <string to append>\n"); fprintf(stderr,"USAGE: examples:\n"); fprintf(stderr,"USAGE: ./blaster queries.fromlog 10 1\n"); fprintf(stderr,"USAGE: ./blaster -r3http://www.gigablast.com/index.php?q= 1 100\n"); return 1; } fprintf(stderr,"Logging to /tmp/blasterLog\n"); // init the loop if ( ! g_loop.init() ) { log("blaster::Loop init failed" ); return 1; } // . then dns client // . server should listen to a socket and register with g_loop if ( ! g_dns.init(6000) ) { log("blaster::Dns client init failed" ); return 1; } // . then webserver // . server should listen to a socket and register with g_loop for(int32_t i = 0; i < 50; i++) { if ( ! g_httpServer.init( 8333 + i, 9334+i ) ) { log("blaster::HttpServer init failed" ); //return 1; } else break; } // set File class char *fname = argv[1]; int32_t fnameLen = gbstrlen(fname); int32_t fileSize = 0; int32_t bufSize = 0; char *buf = NULL; int32_t n = 0; //should we generate random queries? if(fnameLen > 2 && fname[0] == '-' && fname[1] == 'r') { char *p = fname + 2; s_numRandWords = atoi( p ); while(is_digit(*p)) p++; getWords(); if(*p == '\0') goto printUsage; s_server = p; log("blaster server is %s", s_server); // char x[1024]; // while(1) { // int32_t l = getRandomWords(x, x + 1024, s_numRandWords); // *(x + l) = '\0'; // log("blaster: %s", x); // } // exit(1); } else { //it is a real file File f; f.set ( fname ); // open file if ( ! f.open ( O_RDONLY ) ) { log("blaster::open: %s %s",fname,mstrerror(g_errno)); return 1; } // get file size fileSize = f.getFileSize() ; // store a \0 at the end bufSize = fileSize + 1; // make buffer to hold all buf = (char *) mmalloc ( bufSize , "blaster" ); if ( ! buf) {log("blaster::mmalloc: %s",mstrerror(errno));return 1;} //char *bufEnd = buf + bufSize; // set s_p s_p = buf; s_pend = buf + bufSize - 1; // read em all in if ( ! f.read ( buf , fileSize , 0 ) ) { log("blaster::read: %s %s",fname,mstrerror(g_errno));return 1;} // change \n to \0 //char *p = buf; for ( int32_t i = 0 ; i < bufSize ; i++ ) { if ( buf[i] != '\n' ) continue; buf[i] = '\0'; n++; } f.close(); } // log a msg log(LOG_INIT,"blaster: read %"INT32" urls into memory", n ); int32_t linesToSkip = 0; if ( argc >= 5 ) { linesToSkip = atoi ( argv[4] ); log (LOG_INIT,"blaster: skipping %"INT32" urls",linesToSkip); } for ( int32_t i = 0; i < linesToSkip && s_p < s_pend; i++ ) s_p += gbstrlen(s_p) + 1; if ( argc == 6 ) { int32_t len = gbstrlen ( argv[5] ); if ( len > 512 ) len = 512; strncpy ( s_append , argv[5] , gbstrlen (argv[5]) ); } else s_append[0] = '\0'; // get min time bewteen each spider in milliseconds s_wait = atoi( argv[3] ); // # of threads s_maxNumThreads = 1; s_maxNumThreads = atoi ( argv[2] ); s_portSwitch = 0; //if ( argc == 4 ) s_portSwitch = 1; //else s_portSwitch = 0; // start our spider loop //startSpidering( ); // wakeup wrapper every X ms g_loop.registerSleepCallback ( s_wait , NULL , sleepWrapper ); //msg10.addUrls ( uu , gbstrlen(uu)+1, NULL,0,time(0),4,true,NULL,NULL); // . now start g_loops main interrupt handling loop // . it should block forever // . when it gets a signal it dispatches to a server or db to handle it if ( ! g_loop.runLoop() ) { log("blaster::runLoop failed" ); return 1; } // dummy return (0-->normal exit status for the shell) return 0; }
bool SearchInput::set ( TcpSocket *sock , HttpRequest *r , Query *q ) { // get coll rec long collLen; char *coll = r->getString ( "c" , &collLen ); //if (! coll){coll = g_conf.m_defaultColl; collLen = gbstrlen(coll); } if ( ! coll ) coll = g_conf.getDefaultColl(r->getHost(), r->getHostLen()); if ( ! coll ) { g_errno = ENOCOLLREC; return false; } collLen = gbstrlen(coll); CollectionRec *cr = g_collectiondb.getRec ( coll ); if ( ! cr ) { g_errno = ENOCOLLREC; g_msg = " (error: no such collection)"; return false; } // set all to 0 just to avoid any inconsistencies //long size = (char *)&m_END_TEST - (char *)&m_START; //memset ( this , 0x00 , size ); setToDefaults( cr , 0 ); // niceness m_cr = cr; m_coll2 = m_cr->m_coll; m_collLen2 = gbstrlen(m_coll2); // from ::reset() m_languageWeightFactor = 0.33; // Set IP for language detection. // (among other things) if ( sock ) m_queryIP = sock->m_ip; else m_queryIP = 0; m_hr = r; // keep ptr to the query class to use m_q = q; // set this here since its size can be variable m_sq = r->getString("sq",&m_sqLen); // negative docids m_noDocIds = r->getString("nodocids",&m_noDocIdsLen); // negative sites m_noSiteIds = r->getString("nositeids",&m_noSiteIdsLen); // Msg5e calls Msg40 with this set to true in the searchInput // so it can analyze the entire pages of each search result so it // can find the article start/end tag sequence indicators m_getTitleRec = r->getLong("gettrs",0); m_getSitePops = r->getLong("getsitepops",0 ); // does this collection ban this IP? /* long encapIp = 0; m if (! cr->hasSearchPermission ( sock, encapIp ) ) { g_errno = ENOPERM; g_msg = " (error: permission denied)"; return false; } */ // set all search parms in SearchInput to defaults for ( long i = 0 ; i < g_parms.m_numSearchParms ; i++ ) { Parm *m = g_parms.m_searchParms[i]; // sanity if ( m->m_soff < 0 ) { char *xx=NULL;*xx=0; } char *x = (char *)this + m->m_soff; // what is the def val ptr char *def = NULL; if ( m->m_off >= 0 && m->m_obj == OBJ_COLL ) def = ((char *)cr) + m->m_off; else if ( m->m_off >= 0 && m->m_obj == OBJ_CONF ) def = ((char *)&g_conf) + m->m_off; // set it based on type if ( m->m_type == TYPE_LONG ) { long v = 0; if ( def ) v = *(long *)def; else if ( m->m_def ) v = atol(m->m_def); *(long *)x = v; } else if ( m->m_type == TYPE_BOOL ) { long v = 0; if ( def ) v = *(char *)def; else if ( m->m_def ) v = atol(m->m_def); // sanity test! if ( v != 0 && v != 1 ) log("query: got non-bool default " "for bool parm %s",m->m_title); if ( v ) *(char *)x = 1; else *(char *)x = 0; } else if ( m->m_type == TYPE_CHAR ) { if ( def ) *(char *)x = *(char *)def; else if ( m->m_def ) *(char *)x = atol(m->m_def); } else if ( m->m_type == TYPE_FLOAT ) { float v = 0; if ( def ) v = *(float *)def; else if ( m->m_def ) v = atof(m->m_def); *(float *)x = (float)v; } else if ( m->m_type == TYPE_STRING || m->m_type == TYPE_STRINGBOX ) { //if ( m->m_cgi && strcmp ( m->m_cgi, "erpc" ) == 0 ) // log("hey1"); //if ( m->m_cgi && strcmp ( m->m_scgi, "q" ) == 0 ) // log("hey1"); char *v = NULL; if ( def ) v = (char *)def; else if ( m->m_def ) v = m->m_def; *(char **)x = v; // set the length if ( ! v ) *(long *)(x-4) = 0; else *(long *)(x-4) = gbstrlen(v); } } // this is just used to determine in PageResults.cpp if we should // show admin knobs next to each result... // default to off for now m_isAdmin = r->getLong("admin",0); //if ( m_isAdmin ) m_isAdmin = g_users.hasPermission ( r , PAGE_MASTER ); // local ip? if ( ! r->isLocal() ) m_isAdmin = 0; // default set does not take into account g_conf, // so we will take care of that here ourselves... m_adFeedEnabled = g_conf.m_adFeedEnabled; //m_excludeLinkText = g_conf.m_excludeLinkText; //m_excludeMetaText = g_conf.m_excludeMetaText; // we need to get some cgi values in order to correct the defaults // based on if we're doing an xml feed, have a site: query, etc. long xml = r->getLong ( "xml" , 0 ); // was "raw" long siteLen = 0; r->getString ("site",&siteLen); long sitesLen = 0; char *sites = r->getString ("sites",&sitesLen,NULL); // save it if there if ( sites && sitesLen > 0 && ( ! m_whiteListBuf.safeStrcpy(sites)|| ! m_whiteListBuf.nullTerm() ) ) return log("query: unable to strcpy whitelist"); // now override automatic defaults for special cases if ( xml > 0 ) { m_familyFilter = 0; // this is causing me a headache when on when i dont know it m_restrictIndexdbForQuery = false; // this is hackish if ( r->getLong("rt",0) ) m_restrictIndexdbForQuery=false; m_numTopicsToDisplay = 0; m_doQueryHighlighting = 0; m_spellCheck = 0; m_refs_numToGenerate = 0; m_refs_docsToScan = 0; } else if ( m_siteLen > 0 ) { m_restrictIndexdbForQuery = false; m_doSiteClustering = false; m_ipRestrictForTopics = false; } else if ( m_whiteListBuf.length() > 0 ) { m_ipRestrictForTopics = false; } m_doIpClustering = false; //m_sitesQueryLen = 0; // set the user ip, "uip" long uip = m_queryIP; char *uipStr = m_hr->getString ("uip" , NULL ); long tmpIp = 0; if ( uipStr ) tmpIp = atoip(uipStr); if ( tmpIp ) uip = tmpIp; // // // BEGIN MAIN PARM SETTING LOOP // // // loop through all possible cgi parms to set SearchInput for ( long i = 0 ; i < g_parms.m_numSearchParms ; i++ ) { Parm *m = g_parms.m_searchParms[i]; char *x = (char *)this + m->m_soff; // what is the parm's cgi name? char *cgi = m->m_scgi; if ( ! cgi ) cgi = m->m_cgi; // sanity check if ( ! m->m_sparm ) { log("query: Failed search input sanity check."); char *xx = NULL; *xx = 0; } // . break it down by type now // . get it from request and store it in SearchInput if ( m->m_type == TYPE_LONG ) { // default was set above long def = *(long *)x; // assume default long v = def; // but cgi parms override cookie v = r->getLong ( cgi , v ); // but if its a privledged parm and we're not an admin // then do not allow overrides, but m_priv of 3 means // to not display for clients, but to allow overrides if ( ! m_isAdmin && m->m_priv && m->m_priv!=3) v = def; // bounds checks if ( v < m->m_smin ) v = m->m_smin; if ( v > m->m_smax ) v = m->m_smax; if ( m->m_sminc >= 0 ) { long vmin = *(long *)((char *)cr+m->m_sminc); if ( v < vmin ) v = vmin; } if ( m->m_smaxc >= 0 ) { long vmax = *(long *)((char *)cr+m->m_smaxc); if ( v > vmax ) v = vmax; } // set it *(long *)x = v; // do not print start result num (m->m_sprop is 0 for // "s" now) //if ( cgi[0] == 's' && cgi[1] == '\0' ) continue; // should we propagate it? true by default //if ( ! m->m_sprop ) continue; // if it is the same as its default, and the default is // always from m_def and never from the CollectionRec, // then do not both storing it in here! what's the // point? if ( v == def && m->m_off < 0 ) continue; // if not default do not propagate if ( v == def ) continue; // . include for sure if explicitly provided // . vp will be NULL if "cgi" is not explicitly listed // as a cgi parm. otherwise, even if *vp == '\0', vp // is non-NULL. // . crap, it can be in the cookie now //char *vp = r->getValue(cgi, NULL, NULL); // if not given at all, do not propagate //if ( ! vp ) continue; // store in up if different from default, even if // same as default ("def") because default may be // changed by the admin since m->m_off >= 0 //if ( m->m_sprpg && up + gbstrlen(cgi) + 20 < upend ) // up += sprintf ( up , "%s=%li&", cgi , v ); //if ( m->m_sprpp && pp + gbstrlen(cgi) + 80 < ppend ) // pp += sprintf ( pp , "<input type=hidden " // "name=%s value=\"%li\">\n", // cgi , v ); } else if ( m->m_type == TYPE_FLOAT ) { // default was set above float def = *(float *)x; // get overriding from http request, if any float v; // but if its a privledged parm and we're not an admin // then do not allow overrides if ( ! m_isAdmin && m->m_priv && m->m_priv!=3) v = def; else v = r->getFloat( cgi , def ); // bounds checks if ( v < m->m_smin ) v = m->m_smin; if ( v > m->m_smax ) v = m->m_smax; if ( m->m_sminc >= 0 ) { float vmin = *(float *)((char *)cr+m->m_sminc); if ( v < vmin ) v = vmin; } if ( m->m_smaxc >= 0 ) { float vmax = *(float *)((char *)cr+m->m_smaxc); if ( v > vmax ) v = vmax; } // set it *(float *)x = v; // do not print start result num //if ( cgi[0] == 's' && cgi[1] == '\0' ) continue; // include for sure if explicitly provided char *vp = r->getValue(cgi, NULL, NULL); if ( ! vp ) continue; // unchanged from default? if ( v == def ) continue; // store in up different from default //if ((vp||v!= def) && up + gbstrlen(cgi)+20 < upend ) // up += sprintf ( up , "%s=%f&", cgi , v ); //if ((vp||v!= def) && pp + gbstrlen(cgi)+20 < ppend ) // pp += sprintf ( pp , "<input type=hidden " // "name=%s value=\"%f\">\n", // cgi , v ); } else if ( m->m_type == TYPE_BOOL ) { // default was set above long def = *(char *)x; if ( def != 0 ) def = 1; // normalize // assume default long v = def; // cgi parms override cookie v = r->getBool ( cgi , v ); // but if no perm, use default if ( ! m_isAdmin && m->m_priv && m->m_priv!=3) v = def; if ( v != 0 ) v = 1; // normalize *(char *)x = v; // don't propagate rcache //if ( ! strcmp(cgi,"rcache") ) continue; // should we propagate it? true by default //if ( ! m->m_sprop ) continue; // if it is the same as its default, and the default is // always from m_def and never from the CollectionRec, // then do not both storing it in here! what's the // point? if ( v == def && m->m_off < 0 ) continue; // if not default do not propagate if ( v == def ) continue; // . include for sure if explicitly provided // . vp will be NULL if "cgi" is not explicitly listed // as a cgi parm. otherwise, even if *vp == '\0', vp // is non-NULL. // . crap, it can be in the cookie now! //char *vp = r->getValue(cgi, NULL, NULL); // if not given at all, do not propagate //if ( ! vp ) continue; // store in up if different from default, even if // same as default ("def") because default may be // changed by the admin since m->m_off >= 0 //if ( m->m_sprpg && up + gbstrlen(cgi) + 10 < upend ) // up += sprintf ( up , "%s=%li&", cgi , v ); //if ( m->m_sprpp && pp + gbstrlen(cgi) + 80 < ppend ) // pp += sprintf ( pp , "<input type=hidden " // "name=%s value=\"%li\">\n", // cgi , v ); } else if ( m->m_type == TYPE_CHAR ) { // default was set above char def = *(char *)x; *(char *)x = r->getLong ( cgi, def ); // use this long v = *(char *)x; // store in up if different from default, even if // same as default ("def") because default may be // changed by the admin since m->m_off >= 0. nah, // let's try to reduce cgi parm pollution... if ( v == def ) continue; //if ( m->m_sprpg && up + gbstrlen(cgi) + 10 < upend ) // up += sprintf ( up , "%s=%li&", cgi , v ); //if ( m->m_sprpp && pp + gbstrlen(cgi) + 80 < ppend ) // pp += sprintf ( pp , "<input type=hidden " // "name=%s value=\"%li\">\n", // cgi , v ); } else if ( m->m_type == TYPE_STRING || m->m_type == TYPE_STRINGBOX ) { //if ( m->m_cgi && strcmp ( m->m_cgi, "qlang" ) == 0 ) // log("hey2"); char *def = *(char **)x; // get overriding from http request, if any long len = 0; char *v = NULL; // . cgi parms override cookie // . is this url encoded? v = r->getString ( cgi , &len , v ); // if not specified explicitly, default it and continue if ( ! v ) { // sanity if ( ! def ) def = ""; *(char **)x = def; // length preceeds char ptr in SearchInput *(long *)(x - 4) = gbstrlen(def); continue; } // if something was specified, override, it might // be length zero, too *(char **)x = v; // length preceeds char ptr in SearchInput *(long *)(x - 4) = len; // do not store if query, that needs to be last so // related topics can append to it //if ( cgi[0] == 'q' && cgi[1] == '\0' ) continue; // should we propagate it? true by default //if ( ! m->m_sprop ) continue; // if not given at all, do not propagate //if ( ! vp ) continue; // if it is the same as its default, and the default is // always from m_def and never from the CollectionRec, // then do not both storing it in here! what's the // point? //if ( v && v == def && !strcmp(def,v) && m->m_off < 0) // continue; // Need to set qcs based on page encoding... // not propagated if (!strncmp(cgi, "qcs", 3)) continue; // do not propagate defaults if ( v == def ) continue; // store in up if different from default, even if // same as default ("def") because default may be // changed by the admin since m->m_off >= 0 //if( m->m_sprpg && up+gbstrlen(cgi)+len+6 < upend ) { // up += sprintf ( up , "%s=", cgi ); // up += urlEncode ( up , upend-up-2 , v , len ); // *up++ = '&'; //} // propogate hidden inputs //if ( m->m_sprpp && up+gbstrlen(cgi)+len+80 < upend ) // pp += sprintf ( pp , "<input type=hidden " // "name=%s value=\"%s\">\n", // cgi , v ); } } // now add the special "qh" parm whose default value changes // depending on if we are widget related or not long qhDefault = 1; m_doQueryHighlighting = r->getLong("qh",qhDefault); // // TODO: use Parms.cpp defaults // TopicGroup *tg = &m_topicGroups[0]; // // // gigabits // // tg->m_numTopics = 50; tg->m_maxTopics = 50; tg->m_docsToScanForTopics = m_docsToScanForTopics; tg->m_minTopicScore = 0; tg->m_maxWordsPerTopic = 6; tg->m_meta[0] = '\0'; tg->m_delimeter = '\0'; tg->m_useIdfForTopics = false; tg->m_dedup = true; // need to be on at least 2 pages! tg->m_minDocCount = 2; tg->m_ipRestrict = true; tg->m_dedupSamplePercent = 80; tg->m_topicRemoveOverlaps = true; tg->m_topicSampleSize = 4096; // max sequential punct chars allowedin a topic tg->m_topicMaxPunctLen = 1; m_numTopicGroups = 1; // use "&dg=1" to debug gigabits m_debugGigabits = r->getLong("dg",0); // . omit scoring info from the xml feed for now // . we have to roll this out to gk144 net i think if ( xml > 0 ) m_getDocIdScoringInfo = 0; // turn off by default! if ( ! r->getLong("gigabits",0) ) { m_numTopicGroups = 0; } ////////////////////////////////////// // // transform input into classes // ////////////////////////////////////// // USER_ADMIN, ... m_username = g_users.getUsername(r); // if collection is NULL default to one in g_conf if ( ! m_coll2 || ! m_coll2[0] ) { //m_coll = g_conf.m_defaultColl; m_coll2 = g_conf.getDefaultColl(r->getHost(), r->getHostLen()); m_collLen2 = gbstrlen(coll); } // reset this m_gblang = 0; // use gblang then! long gglen; char *gg = r->getString ( "clang" , &gglen , NULL ); if ( gg && gglen > 1 ) m_gblang = getLanguageFromAbbr(gg); // allow for "qlang" if still don't have it //long gglen2; //char *gg2 = r->getString ( "qlang" , &gglen2 , NULL ); //if ( m_gblang == 0 && gg2 && gglen2 > 1 ) // m_gblang = getLanguageFromAbbr(gg2); // fix query by removing lang:xx from ask.com queries //char *end = m_query + m_queryLen -8; //if ( m_queryLen > 8 && m_query && end > m_query && // strncmp(end," lang:",6)==0 ) { // char *asklang = m_query+m_queryLen - 2; // m_gblang = getLanguageFromAbbr(asklang); // m_queryLen -= 8; // m_query[m_queryLen] = 0; // //} // . returns false and sets g_errno on error // . sets m_qbuf1 and m_qbuf2 if ( ! setQueryBuffers (r) ) return log("query: setQueryBuffers: %s",mstrerror(g_errno)); /* --- Virtual host language detection --- */ if(r->getHost()) { bool langset = getLanguageFromAbbr(m_defaultSortLanguage); char *cp; if(!langset && (cp = strrchr(r->getHost(), '.'))) { uint8_t lang = getLanguageFromUserAgent(++cp); if(lang) { // char langbuf[128]; // sprintf(langbuf, "qlang=%s\0", getLanguageAbbr(lang)); //m_defaultSortLanguage = getLanguageAbbr(lang); char *tmp = getLanguageAbbr(lang); strncpy(m_defaultSortLanguage, tmp, 6); // log(LOG_INFO, // getLanguageString(lang), r->getHost(), this); } } } /* --- End Virtual host language detection --- */ char *qs1 = m_defaultSortLanguage; // this overrides though //long qlen2; //char *qs2 = r->getString ("qlang",&qlen2,NULL); //if ( qs2 ) qs1 = qs2; m_queryLang = getLanguageFromAbbr ( qs1 ); if ( qs1 && qs1[0] && ! m_queryLang ) log("query: qlang of \"%s\" is NOT SUPPORTED",qs1); // . the query to use for highlighting... can be overriden with "hq" // . we need the language id for doing synonyms if ( m_highlightQuery && m_highlightQuery[0] ) m_hqq.set2 ( m_highlightQuery , m_queryLang , true ); else if ( m_query && m_query[0] ) m_hqq.set2 ( m_query , m_queryLang , true ); // log it here log("query: got query %s",m_sbuf1.getBufStart()); // . now set from m_qbuf1, the advanced/composite query buffer // . returns false and sets g_errno on error (ETOOMANYOPERANDS) if ( ! m_q->set2 ( m_sbuf1.getBufStart(), m_queryLang , m_queryExpansion ) ) { g_msg = " (error: query has too many operands)"; return false; } if ( m_q->m_truncated && m_q->m_isBoolean ) { g_errno = ETOOMANYOPERANDS; g_msg = " (error: query has too many operands)"; return false; } // do not allow querier to use the links: query operator unless they // are admin or the search controls explicitly allow links: //if ( m_q->m_hasLinksOperator && ! m_isAdmin && // !cr->m_allowLinksSearch ) { // g_errno = ENOPERM; // g_msg = " (error: permission denied)"; // return false; //} // miscellaneous m_showBanned = false; //if ( m_isAdmin ) m_showBanned = true; // admin can say &sb=0 explicitly to not show banned results if ( m_isAdmin ) m_showBanned = r->getLong("sb",m_showBanned); if ( m_q->m_hasUrlField ) m_ipRestrictForTopics = false; if ( m_q->m_hasIpField ) { m_ipRestrictForTopics = false; //if( m_isAdmin ) m_showBanned = true; } if ( m_q->m_hasPositiveSiteField ) { m_ipRestrictForTopics = false; m_doSiteClustering = false; } if ( m_q->m_hasQuotaField ) { m_doSiteClustering = false; m_doDupContentRemoval = false; } m_familyFilter = r->getLong("ff",0); long codeLen; char *code = r->getString ("code",&codeLen,NULL); // set m_endUser if ( ! codeLen || ! code || strcmp(code,"gbfront")==0 ) m_endUser = true; else m_endUser = false; if(codeLen && !m_endUser) { m_maxResults = cr->m_maxSearchResultsForClients; } else { m_maxResults = cr->m_maxSearchResults; } // don't let admin bewilder himself if ( m_maxResults < 1 ) m_maxResults = 500; // we can't get this kind of constraint from generic Parms routines if ( m_firstResultNum + m_docsWanted > m_maxResults ) m_firstResultNum = m_maxResults - m_docsWanted; if(m_firstResultNum < 0) m_firstResultNum = 0; // if useCache is -1 then pick a default value if ( m_useCache == -1 ) { // assume yes as default m_useCache = 1; // . if query has url: or site: term do NOT use cache by def. // . however, if spider is off then use the cache by default if ( g_conf.m_spideringEnabled ) { if ( m_q->m_hasPositiveSiteField ) m_useCache = 0; else if ( m_q->m_hasIpField ) m_useCache = 0; else if ( m_q->m_hasUrlField ) m_useCache = 0; else if ( m_siteLen > 0 ) m_useCache = 0; else if ( m_whiteListBuf.length() ) m_useCache = 0; else if ( m_urlLen > 0 ) m_useCache = 0; } } // never use cache if doing a rerank (msg3b) //if ( m_rerankRuleset >= 0 ) m_useCache = 0; bool readFromCache = false; if ( m_useCache == 1 ) readFromCache = true; if ( m_rcache == 0 ) readFromCache = false; if ( m_useCache == 0 ) readFromCache = false; // if useCache is false, don't write to cache if it was not specified if ( m_wcache == -1 ) { if ( m_useCache == 0 ) m_wcache = 0; else m_wcache = 1; } // save it m_rcache = readFromCache; /* m_language = 0; // convert m_languageCode to a number for m_language if ( m_languageCode ) { m_language = (unsigned char)atoi(m_languageCode); if ( m_language == 0 ) m_language = getLanguageFromAbbr(m_languageCode); } */ // a hack for buzz for backwards compatibility //if ( strstr ( m_q->m_orig,"gbkeyword:r36p1" ) ) // m_ruleset = 36; // // . turn this off for now // . it is used in setClusterLevels() to use clusterdb to filter our // search results via Msg39, so it is not the most efficient. // . plus i am deleting most foreign language pages from the index // so we can just focus on english and that will give us more english // pages that we could normally get. we don't have resources to // de-spam the other languages, etc. // . turn it back on, i took out the setClusterLevels() use of that // because we got the langid in the posdb keys now // //m_language = 0; // convert m_defaultSortCountry to a number for m_countryHint m_countryHint = g_countryCode.getIndexOfAbbr(m_defaultSortCountry); return true; }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno) { // check ignore list int i; for (i = 0; i < MAX_PROFILE_IGNORE; i++) { if (cfg.profile_ignore[i] == NULL) break; if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0) return 0; // ignore line } if (strncmp(ptr, "ignore ", 7) == 0) { char *str = strdup(ptr + 7); if (*str == '\0') { fprintf(stderr, "Error: invalid ignore option\n"); exit(1); } // find an empty entry in profile_ignore array int j; for (j = 0; j < MAX_PROFILE_IGNORE; j++) { if (cfg.profile_ignore[j] == NULL) break; } if (j >= MAX_PROFILE_IGNORE) { fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); exit(1); } // ... and configure it cfg.profile_ignore[j] = str; return 0; } // seccomp, caps, private, user namespace if (strcmp(ptr, "noroot") == 0) { check_user_namespace(); return 0; } else if (strcmp(ptr, "seccomp") == 0) { arg_seccomp = 1; return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps_default_filter = 1; return 0; } else if (strcmp(ptr, "caps.drop all") == 0) { arg_caps_drop_all = 1; return 0; } else if (strcmp(ptr, "shell none") == 0) { arg_shell_none = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } else if (strcmp(ptr, "private-dev") == 0) { arg_private_dev = 1; return 0; } else if (strcmp(ptr, "nogroups") == 0) { arg_nogroups = 1; return 0; } else if (strcmp(ptr, "netfilter") == 0) { arg_netfilter = 1; return 0; } else if (strncmp(ptr, "netfilter ", 10) == 0) { arg_netfilter = 1; arg_netfilter_file = strdup(ptr + 10); if (!arg_netfilter_file) errExit("strdup"); check_netfilter_file(arg_netfilter_file); return 0; } else if (strcmp(ptr, "net none") == 0) { arg_nonetwork = 1; cfg.bridge0.configured = 0; cfg.bridge1.configured = 0; cfg.bridge2.configured = 0; cfg.bridge3.configured = 0; return 0; } if (strncmp(ptr, "protocol ", 9) == 0) { protocol_store(ptr + 9); return 0; } if (strncmp(ptr, "env ", 4) == 0) { env_store(ptr + 4); return 0; } // seccomp drop list on top of default list if (strncmp(ptr, "seccomp ", 8) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP cfg.seccomp_list = strdup(ptr + 8); if (!cfg.seccomp_list) errExit("strdup"); #endif return 0; } // seccomp drop list without default list if (strncmp(ptr, "seccomp.drop ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP cfg.seccomp_list_drop = strdup(ptr + 13); if (!cfg.seccomp_list_drop) errExit("strdup"); #endif return 0; } // seccomp keep list if (strncmp(ptr, "seccomp.keep ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP cfg.seccomp_list_keep= strdup(ptr + 13); if (!cfg.seccomp_list_keep) errExit("strdup"); #endif return 0; } // caps drop list if (strncmp(ptr, "caps.drop ", 10) == 0) { arg_caps_drop = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // caps keep list if (strncmp(ptr, "caps.keep ", 10) == 0) { arg_caps_keep = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; if (atoip(ptr + 4, &dns)) { fprintf(stderr, "Error: invalid DNS server IP address\n"); return 1; } if (cfg.dns1 == 0) cfg.dns1 = dns; else if (cfg.dns2 == 0) cfg.dns2 = dns; else if (cfg.dns3 == 0) cfg.dns3 = dns; else { fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); return 1; } return 0; } // cpu affinity if (strncmp(ptr, "cpu ", 4) == 0) { read_cpu_list(ptr + 4); return 0; } // cgroup if (strncmp(ptr, "cgroup ", 7) == 0) { set_cgroup(ptr + 7); return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; fs_check_private_dir(); arg_private = 1; return 0; } // private home list of files and directories if ((strncmp(ptr, "private.keep ", 13) == 0) || (strncmp(ptr, "private-home ", 13) == 0)) { cfg.home_private_keep = ptr + 13; fs_check_home_list(); arg_private = 1; return 0; } // private /etc list of files and directories if (strncmp(ptr, "private-etc ", 12) == 0) { cfg.etc_private_keep = ptr + 12; fs_check_etc_list(); arg_private_etc = 1; return 0; } // private /bin list of files if (strncmp(ptr, "private-bin ", 12) == 0) { cfg.bin_private_keep = ptr + 12; fs_check_bin_list(); arg_private_bin = 1; return 0; } // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: mising second directory for bind\n"); exit(1); } // check directories invalid_filename(dname1); invalid_filename(dname2); if (strstr(dname1, "..") || strstr(dname2, "..")) { fprintf(stderr, "Error: invalid file name.\n"); exit(1); } // insert comma back *(dname2 - 1) = ','; return 1; } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { ptr += 14; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { ptr += 18; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "noblacklist ", 12) == 0) ptr += 12; else if (strncmp(ptr, "whitelist ", 10) == 0) { arg_whitelist = 1; ptr += 10; } else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "tmpfs ", 6) == 0) ptr += 6; else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames invalid_filename(ptr); if (strstr(ptr, "..")) { if (lineno == 0) fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } return 1; }
bool AutoBan::printTable( TcpSocket *s , HttpRequest *r ) { SafeBuf sb(512 * 512,"autobbuf"); //read in all of the possible cgi parms off the bat: //long user = g_pages.getUserType( s , r ); char *username = g_users.getUsername(r); //char *pwd = r->getString ("pwd"); char *coll = r->getString ("c"); long banIpsLen; char *banIps = r->getString ("banIps" , &banIpsLen , NULL); long allowIpsLen; char *allowIps = r->getString ("allowIps" , &allowIpsLen , NULL); long clearLen; char *clear = r->getString ("clear" , &clearLen , NULL); bool changed = false; long validCodesLen; char *validCodes = r->getString ("validCodes", &validCodesLen, NULL); long showAllIps = r->getLong("showAllIps", 0); long showLongView = r->getLong("longview", 0); // do it all from parm now //long banRegexLen; //char *banRegex = r->getString("banRegex", &banRegexLen, NULL); // char *ss = sb.getBuf(); // char *ssend = sb.getBufEnd(); g_pages.printAdminTop ( &sb, PAGE_AUTOBAN, username, coll , NULL , s->m_ip ); //sb.incrementLength(sss - ss); // MDW: moved to here long now = getTime(); long days; long hours; long minutes; long secs; long msecs; if(r->getLong("resetcodes", 0)) { setCodesFromConf(); } sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); getCalendarFromMs((now - m_codeResetTime) * 1000, &days, &hours, &minutes, &secs, &msecs); sb.safePrintf("<tr><td colspan=18 bgcolor=#%s>" "<center><b>Code Usage " "(<a href=\"/master/" "autoban?c=%s&resetcodes=1\">reset</a> " "%li days %li hours %li " "minutes %li sec ago)" "</b></center></td></tr>", DARK_BLUE, coll, days, hours, minutes, secs); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>Code</b></center></td>" "<td><center><b>IP</b></center></td>" "<td><center><b>Query Count</b></center></td>" "<td><center><b>Bytes Read</b></center></td>" "<td><center><b>Bytes Sent</b></center></td>" "<td><center><b>Outstanding Count</b></center></td>" "<td><center><b>Most Ever Outstanding</b></center></td>" "<td><center><b>Max Outstanding</b></center></td>" "</tr>", LIGHT_BLUE); for(long i = 0; i < m_ht.getNumSlots(); i++) { if ( m_ht.getKey ( i ) == 0 ) continue; CodeVal *cv = m_ht.getValuePointerFromSlot ( i ); if ( ! cv ) continue; sb.safePrintf("<tr>"); sb.safePrintf("<td>"); sb.copyToken(cv->m_code);//m_codeVals[i].m_code); sb.safePrintf("</td>"); sb.safePrintf("<td><center>%s</center> </td>", iptoa(cv->m_ip)); sb.safePrintf("<td><center>%lli</center></td>", cv->m_count); sb.safePrintf("<td><center>%lli</center></td>", cv->m_bytesRead); sb.safePrintf("<td><center>%lli</center></td>", cv->m_bytesSent); sb.safePrintf("<td><center>%li</center></td>", cv->m_outstanding); sb.safePrintf("<td><center>%li</center></td>", cv->m_maxEver); if ( cv->m_maxOutstanding != 50 ) sb.safePrintf("<td><center><b>%li</b></center></td>", cv->m_maxOutstanding); else sb.safePrintf("<td><center>%li</center></td>", cv->m_maxOutstanding); sb.safePrintf("</tr>"); } sb.safePrintf ("</table><br><br>\n" ); if(clear && clearLen < 64) { long ip = atoip(clear, clearLen); if(ip) { removeIp(ip); char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, clear, clearLen); ipbuf[clearLen] = '\0'; beginning = findToken(g_conf.m_banIps, ipbuf, clearLen); if(beginning) { char *to = beginning; char *from = beginning + clearLen; while(*to) *to++ = *from++; } beginning = findToken(g_conf.m_allowIps, ipbuf, clearLen); if(beginning) { char *to = beginning; char *from = beginning + clearLen; while(*to) *to++ = *from++; } changed = true; } } long allowLen; char *allow = r->getString ( "allow" , &allowLen , NULL ); if(allow && allowLen < 64) { long ip = atoip(allow, allowLen); if(ip) { char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, allow, allowLen); ipbuf[allowLen] = '\0'; beginning = findToken(g_conf.m_allowIps, ipbuf, allowLen); if(!beginning) { //its not present, so add it. char *p = g_conf.m_allowIps; while(*p) p++; if(p - g_conf.m_allowIps + allowLen + 2 < AUTOBAN_TEXT_SIZE) { *p++ = '\n'; memcpy(p, ipbuf,allowLen); *(p + allowLen) = '\0'; } else { sb.safePrintf("<font color=red>" "Not enough stack space " "to fit allowIps. " "Increase " "AUTOBAN_TEXT_SIZE in " "Conf.h. " "Had %i need %li." "</font>", AUTOBAN_TEXT_SIZE, p - g_conf.m_allowIps + allowLen + 2); goto dontRemove1; } } beginning = findToken(g_conf.m_banIps, ipbuf, allowLen); if(beginning) { //remove it from banned if present. char *to = beginning; char *from = beginning + allowLen; while(*to) *to++ = *from++; } changed = true; } } dontRemove1: long denyLen; char *deny = r->getString ( "deny" , &denyLen , NULL ); if(deny && denyLen < 64) { long ip = atoip(deny, denyLen); if(ip) { char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, deny, denyLen); ipbuf[denyLen] = '\0'; beginning = findToken(g_conf.m_banIps, ipbuf, denyLen); if(!beginning) { //its not present, so add it. char *p =g_conf.m_banIps; while(*p) p++; if(p - g_conf.m_banIps + denyLen + 2 < AUTOBAN_TEXT_SIZE) { *p++ = '\n'; memcpy(p, ipbuf,denyLen); *(p + denyLen) = '\0'; } else { sb.safePrintf("<font color=red>Not " "enough stack space " "to fit bannedIPs. " "Increase " "AUTOBAN_TEXT_SIZE in " "Conf.h. " "Had %i need %li." "</font>", AUTOBAN_TEXT_SIZE, p - g_conf.m_banIps + denyLen + 2); goto dontRemove2; } } beginning = findToken(g_conf.m_allowIps, ipbuf, denyLen); if(beginning) { //remove it from allowed list if present. char *to = beginning; char *from = beginning + denyLen; while(*to) *to++ = *from++; } changed = true; } } dontRemove2: if(!g_conf.m_doAutoBan) { sb.safePrintf("<center><font color=red><b>Autoban is disabled, " "turn it on in Master Controls.</b></font></center><br>"); } if(validCodes) { if(validCodesLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit codes. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, validCodesLen); validCodes = NULL; validCodesLen = 0; } else { memcpy(g_conf.m_validCodes, validCodes, validCodesLen); g_conf.m_validCodes[validCodesLen] = '\0'; trimWhite(g_conf.m_validCodes); setCodesFromConf(); } } //first remove all of the ips in the conf, then add the passed in // ones to the conf parm; if (banIps) { //ack, the browser puts in crlf when this comes back, so //we will have a longer string here than the one we sent //out. trim back all extrainious whitespace before we do //bounds checking. trimWhite(banIps); banIpsLen = gbstrlen(banIps); if(banIpsLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit bannedIps. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, banIpsLen); banIpsLen = AUTOBAN_TEXT_SIZE - 1; } for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; //check the 'set from conf' bit, and clear those. if(m_detectVals[i].m_flags & FROMCONF) { removeIp(m_detectKeys[i]); } } memcpy(g_conf.m_banIps, banIps, banIpsLen); g_conf.m_banIps[banIpsLen] = '\0'; changed = true; } if (allowIps) { trimWhite(allowIps); allowIpsLen = gbstrlen(allowIps); if(allowIpsLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit allowIps. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, allowIpsLen); allowIpsLen = AUTOBAN_TEXT_SIZE - 1; } for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; //check the 'set from conf' bit, and clear those. if(m_detectVals[i].m_flags & FROMCONF) { removeIp(m_detectKeys[i]); } } memcpy(g_conf.m_allowIps, allowIps, allowIpsLen); g_conf.m_allowIps[allowIpsLen] = '\0'; changed = true; } if(changed) { trimWhite(g_conf.m_allowIps); trimWhite(g_conf.m_banIps); setFromConf(); } sb.safePrintf("\n<table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=2 bgcolor=#%s>" "<center><b>Add IPs</b></center></td></tr>", DARK_BLUE); // ss = sb.getBuf(); // ssend = sb.getBufEnd(); g_parms.printParms (&sb, s, r); // sb.incrementLength(sss - ss); sb.safePrintf ("<tr><td>" "<center>" "<input type=submit value=\"Update\" " "method=\"POST\" border=0>" "</center></td></tr>"); sb.safePrintf ("</table><br><br>\n" ); if(!showLongView) { sb.safePrintf("<b><a href=\"autoban" "?c=%s" "&showAllIps=%li" "&longview=1\">Show watched ips table...</a></b>", coll, showAllIps); return g_httpServer.sendDynamicPage ( s , sb.getBufStart() , sb.length() , -1 , false); } ///////////////////////////////////////////////////////////////////// sb.safePrintf("\n<table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=3 bgcolor=#%s>" "<center><b>Watched Ips</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>IP</b></center></td>" "<td><center><b>Description</b></center></td>" // "<td><center><b>Time Added</b></center></td>" "<td><center><b>Allow/Deny/Clear</b></center></td>" "</tr>", LIGHT_BLUE); long *sortedIndices = (long*)mmalloc(m_tableSize * sizeof(long), "AutoBanH"); if(!sortedIndices) { return g_httpServer.sendErrorReply(s,500,mstrerror(ENOMEM)); } long numEntries = 0; for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; sortedIndices[numEntries++] = i; } SorterTable = m_detectKeys; gbsort(sortedIndices, numEntries, sizeof(long), ip_cmp); //lets put each class of watched ip in its own safebuf then cat //them together at the end. SafeBuf allowed; SafeBuf banned; SafeBuf feedLeachers; SafeBuf cowBots; SafeBuf *e; for(long j = 0; j < numEntries; j++) { long i = sortedIndices[j]; if(m_detectKeys[i] == 0) continue; //if(!(m_detectVals[i].m_flags & FROMCONF)) continue; bool allow = m_detectVals[i].m_flags & ALLOW && m_detectVals[i].m_flags & FROMCONF; bool deny = m_detectVals[i].m_flags & DENY && m_detectVals[i].m_flags & FROMCONF; bool explicitban = deny && m_detectVals[i].m_flags & FROMCONF; unsigned short dayCount = m_detectVals[i].m_dayCount; unsigned char minuteCount = m_detectVals[i].m_minuteCount; bool day = dayCount >= g_conf.m_numFreeQueriesPerDay; bool minute = minuteCount >= g_conf.m_numFreeQueriesPerMinute; char *description; char *color; if(allow) { color = GREEN; description = "Allowed"; e = &allowed; } else if(explicitban) { color = RED; description = "Banned"; e = &banned; } else if(minute) { color = RED; description = "Cow Bot"; e = &cowBots; } else if(day) { color = RED; description = "Feed Leacher"; e = &feedLeachers; } else { //this can happen when someone was banned due to //exceeding the quota, then the quota was lowered. m_detectVals[i].m_flags &= ~DENY; //log("autoban: ohshit-banning %s",iptoa(s->m_ip)); continue; } e->safePrintf("<tr>"); e->safePrintf("<td bgcolor=#%s><center>%s</center></td><td>" "<center>%s</center></td>" // "<td><center>" // "%li days %li hrs %li min ago" // "</center></td>" "<td><center><a href=\"/master/" "autoban?c=%s&allow=%s&showAllIps=%li\">" "allow/</a>" "<a href=\"/master/" "autoban?c=%s&deny=%s&showAllIps=%li\">" "deny/</a>" "<a href=\"/master/" "autoban?c=%s&clear=%s&showAllIps=%li\">" "clear</a></center>" "</td>",color, iptoa(m_detectKeys[i]), description, // days,hours,minutes, coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps); e->safePrintf("</tr>"); } sb.cat(allowed); sb.cat(banned); sb.cat(feedLeachers); sb.cat(cowBots); sb.safePrintf ("</table><br><br>\n" ); // MDW moved from here sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=5 bgcolor=#%s>" "<center><b>Control Panel</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr>" "<td bgcolor=#%s><center><b>Show Ips by Number of Queries" "</b></center></td>", LIGHT_BLUE); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=0\">" "0 Queries</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=1\">" "1 Query</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=10\">" "10 Queries</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=100\">" "100 Queries</a></b>" "</font></center></td></tr>", coll); sb.safePrintf ("</table><br><br>\n"); if(!showAllIps) { char* ss = (char*) sb.getBufStart(); long sslen = sb.length(); mfree(sortedIndices, m_tableSize * sizeof(long),"AutoBanH"); return g_httpServer.sendDynamicPage ( s , ss , sslen , -1 , false); } sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=6 bgcolor=#%s>" "<center><b>Queries Today</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>IP</b></center></td>" "<td><center><b>Minute count</b></center></td>" "<td><center><b>Day count</b></center></td>" "<td><center><b>Time Until Reset</b></center></td>" "<td><center><b>Times Banned</b></center></td>" "<td><center><b>Allow/Deny</b></center></td>" "</tr>", LIGHT_BLUE); char minBuf[128]; char dayBuf[128]; unsigned long lastIpGroup = 0; for(long j = 0; j < numEntries; j++) { long i = sortedIndices[j]; long dayCount = m_detectVals[i].m_dayCount; unsigned char minuteCount = m_detectVals[i].m_minuteCount; if(!(m_detectVals[i].m_flags & FROMCONF)) { if(m_detectVals[i].m_minuteExpires < now) minuteCount = 0; if(!(m_detectVals[i].m_flags & DENY) && m_detectVals[i].m_dayExpires < now) dayCount = 0; } //a hack: if( dayCount < showAllIps) continue; char *color = YELLOW; if(m_detectVals[i].m_flags & ALLOW) { color = GREEN; snprintf(minBuf, 128, "--"); snprintf(dayBuf, 128, "%li", dayCount); } else if(m_detectVals[i].m_flags & DENY) { color = RED; snprintf(minBuf, 128, "--"); snprintf(dayBuf, 128, "%li", dayCount); } else { snprintf(minBuf, 128, "%li", (long)minuteCount); snprintf(dayBuf, 128, "%li", (long)dayCount); } unsigned long thisIpGroup = (unsigned long)m_detectKeys[i] & 0x00ffffff; sb.safePrintf("<tr><center>"); if(m_detectVals[i].m_flags & FROMCONF) { sb.safePrintf("<td bgcolor=#%s><center>%s%s%s</center></td>" "<td><center>%s</center> </td>" "<td><center>%s</center></td>" "<td><center><font color=red>" "<b>NEVER</b>" "</font></center></td>" "<td><center>--</center></td>", color, (thisIpGroup == lastIpGroup)?"<b>":"", iptoa(m_detectKeys[i]), (thisIpGroup == lastIpGroup)?"</b>":"", minBuf, dayBuf); } else { //they haven't done a query since being unbanned, //unban them now so we don't get negative resets displayed. /* no, don't unban the bots!!! MDW yippy project if(m_detectVals[i].m_dayExpires < now) { m_detectVals[i].m_flags &= ~DENY; //log("autoban: dayexpire-unbanning %s", // iptoa(ip)); m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_dayCount = 0; m_detectVals[i].m_minuteCount = 0; sb.safePrintf("</center></tr>"); continue; } */ getCalendarFromMs((m_detectVals[i].m_dayExpires - now)* 1000, &days, &hours, &minutes, &secs, &msecs); sb.safePrintf("<td bgcolor=#%s><center>%s%s%s</center></td>" "<td><center>%s</center> </td>" "<td><center>%s</center></td>" "<td><center><font color=red>" "<b>%li days %li hrs %li min %li sec</b>" "</font></center></td>" "<td><center>%i</center></td>", color, (thisIpGroup == lastIpGroup)?"<b>":"", iptoa(m_detectKeys[i]), (thisIpGroup == lastIpGroup)?"</b>":"", minBuf, dayBuf, days, hours, minutes, secs, m_detectVals[i].m_timesBanned); } sb.safePrintf("<td><center>" "<a href=\"/master/" "autoban?c=%s&allow=%s&showAllIps=%li\">" "allow/</a>" "<a href=\"/master/" "autoban?c=%s&deny=%s&showAllIps=%li\">" "deny</a></center>" "</td>", coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps); sb.safePrintf("</center></tr>"); lastIpGroup = thisIpGroup; } sb.safePrintf ("</table><br><br>\n" ); char* ss = (char*) sb.getBufStart(); long sslen = sb.length(); mfree(sortedIndices, m_tableSize * sizeof(long),"AutoBanH"); return g_httpServer.sendDynamicPage ( s , ss , sslen , -1 , false); }
bool AutoBan::hasPerm(long ip, char *code, long codeLen, char *uip, long uipLen, TcpSocket *s, HttpRequest *r, SafeBuf* testBuf, bool justCheck ) { char *reqStr = r->getRequest(); long reqLen = r->getRequestLen(); long raw = r->getLong("xml", 0); long isHuman = 0; if(code && hasCode(code, codeLen, ip )) { //don't close client's sockets if(s) s->m_prefLevel++; //no ip, but valid code, let them through. if(!uip) return true; ip = atoip(uip, uipLen); // log(LOG_WARN, "has uip %s", uip); if(!ip) return true; //has code and uip, do the check. //the front end can administer a turing test //and tell us to unban them isHuman = r->getLong("ishuman", 0); } // if ip is local and uip is there, use it if ( uip && r->isLocal() ) { // it's local, let it through if( ! uip ) return true; // get the new ip then ip = atoip(uip, uipLen); // log(LOG_WARN, "has uip %s", uip); if ( !ip ) return true; //has code and uip, do the check. } //now we check the ip block which the ip is in. unsigned long ipBlock = (unsigned long)ip & 0x0000ffff; unsigned long i = getSlot((unsigned long)ipBlock); if((unsigned long)m_detectKeys[i] == ipBlock) { if(m_detectVals[i].m_flags & ALLOW) { if ( justCheck ) return true; m_detectVals[i].m_dayCount++; if(s) s->m_prefLevel++; return true; } if(m_detectVals[i].m_flags & DENY) { if ( justCheck ) return false; m_detectVals[i].m_dayCount++; return false; } } //now we check the ip group which the ip is in. unsigned long ipGroup = (unsigned long)ip & 0x00ffffff; i = getSlot((unsigned long)ipGroup); if((unsigned long)m_detectKeys[i] == ipGroup) { if(m_detectVals[i].m_flags & ALLOW) { if ( justCheck ) return true; m_detectVals[i].m_dayCount++; if(s) s->m_prefLevel++; return true; } if(m_detectVals[i].m_flags & DENY) { if ( justCheck ) return false; m_detectVals[i].m_dayCount++; return false; } } i = getSlot((unsigned long)ip); long now = getTime(); long banTest = r->getLong("bantest",0); if ( banTest ) { log("autoban: doing ban test"); goto doTuringTest; } if(m_detectKeys[i] == ip) { if(m_detectVals[i].m_flags & ALLOW) { // do not inc if just checking, like for a gif file if ( justCheck ) return true; //explicitly allowed. //log(LOG_WARN,"autoban: %li allowed.", ip); m_detectVals[i].m_dayCount++; if(s) s->m_prefLevel++; return true; } if(m_detectVals[i].m_flags & DENY) { // do not inc if just checking, like for a gif file if ( justCheck ) return false; //banned by autoban, or explicity banned by matt. long explicitBan = m_detectVals[i].m_flags & FROMCONF; //log(LOG_WARN,"autoban: %li rejected.", ip); if(!explicitBan && // MDW yippy project - no! don't unban bots! //(m_detectVals[i].m_dayExpires < now || isHuman)) { (isHuman)) { //they are unbanned for now, I guess. m_detectVals[i].m_flags &= ~DENY; m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_dayCount = 1; m_detectVals[i].m_minuteCount = 1; log("autoban: auto-unbanning %s",iptoa(ip)); //return true; goto checkSubstr; } m_detectVals[i].m_dayCount++; if(explicitBan) return false; if(uip) return false; goto doTuringTest; } // do not inc if just checking, like a gif file if ( justCheck ) return true; /* if( m_detectVals[i].m_minuteCount > 0 && // two requests in one second? now == m_detectVals[i].m_minuteExpires - 60 ) { m_detectVals[i].m_flags |= DENY; log("autoban: second-banning %s",iptoa(ip)); long banUntil = now + (ONE_DAY * (m_detectVals[i].m_timesBanned + 1)); if(banUntil < 0 || m_detectVals[i].m_timesBanned == 255 ) { m_detectVals[i].m_dayExpires = 0x7fffffff; } else { m_detectVals[i].m_timesBanned++; m_detectVals[i].m_dayExpires =banUntil; } return false; } */ if(m_detectVals[i].m_minuteCount >= g_conf.m_numFreeQueriesPerMinute) { if(m_detectVals[i].m_minuteExpires > now) { //ban 'em, they are a cowbot, so they //don't get the turing test m_detectVals[i].m_flags |= DENY; log("autoban: minute-banning %s",iptoa(ip)); long banUntil = now + (ONE_DAY * (m_detectVals[i].m_timesBanned + 1)); if(banUntil < 0 || m_detectVals[i].m_timesBanned == 255 ) { m_detectVals[i].m_dayExpires = 0x7fffffff; } else { m_detectVals[i].m_timesBanned++; m_detectVals[i].m_dayExpires = banUntil; } return false; //goto doTuringTest; } else { m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_minuteCount = 0; } } if((unsigned long)m_detectVals[i].m_dayCount >= g_conf.m_numFreeQueriesPerDay) { if(m_detectVals[i].m_dayExpires > now) { //ban 'em log("autoban: day-banning %s",iptoa(ip)); m_detectVals[i].m_flags |= DENY; if(m_detectVals[i].m_timesBanned != 255) m_detectVals[i].m_timesBanned++; m_detectVals[i].m_dayExpires = now + (ONE_DAY * m_detectVals[i]. m_timesBanned); if(uip) return false; goto doTuringTest; } else { m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_dayCount = 0; } } m_detectVals[i].m_minuteCount++; m_detectVals[i].m_dayCount++; //return true; goto checkSubstr; } // do not inc if just checking, like for a gif file if ( justCheck ) return true; if(m_detectKeys[i] == 0) { if(m_numEntries * 1.2 > m_tableSize ) { //here we grow the table and adjust i to an //empty slot in the new (bigger) table if(!growTable()) //return true; goto checkSubstr; i = getSlot(ip); } m_detectKeys[i] = ip; m_detectVals[i].m_flags = 0; m_detectVals[i].m_minuteCount = 1; m_detectVals[i].m_dayCount = 1; m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_timesBanned = 0; ++m_numEntries; //log(LOG_WARN,"autoban: %li adding to empty slot.", //ip); //return true; goto checkSubstr; } //we go here if someone is banned and they are trying to search doTuringTest: // sanity! if ( justCheck ) { char *xx=NULL;*xx=0; } if( raw == 0 ) { // did we get a good response from the turing test? if( g_turingTest.isHuman(r)) { m_detectVals[i].m_flags &= ~DENY; //log("autoban: turing-unbanning %s",iptoa(ip)); m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_dayCount = 1; m_detectVals[i].m_minuteCount = 1; log(LOG_INFO, "autoban: ip %s has unbanned " "themselves", iptoa(ip)); return true; } testBuf->safePrintf("<form method=get>"); long queryLen = 0; char* query = r->getValue("q" , &queryLen); long start = r->getLong("s" , 0); if ( query ) testBuf->safePrintf("<input type=hidden name=\"q\" " "value=\"%s\">\n", query); if ( start > 0 ) testBuf->safePrintf("<input type=hidden name=\"s\" " "value=\"%li\">\n", start); long gigabits = r->getLong("gigabits",0); if ( gigabits ) testBuf->safePrintf("<input type=hidden name=gigabits " "value=1>\n"); // // yippy parms // char *ifs = r->getString("input-form",NULL); if ( ifs ) testBuf->safePrintf("<input type=hidden " "name=\"input-form\" " "value=\"%s\">\n", ifs ); char *vs = r->getString("v:sources",NULL); if ( vs ) testBuf->safePrintf("<input type=hidden " "name=\"v:sources\" " "value=\"%s\">\n", vs ); char *vp = r->getString("v:project",NULL); if ( vp ) testBuf->safePrintf("<input type=hidden " "name=\"v:project\" " "value=\"%s\">\n", vp ); char *qp = r->getString("query",NULL); if ( qp ) testBuf->safePrintf("<input type=hidden " "name=\"query\" " "value=\"%s\">\n", qp); if ( banTest ) testBuf->safePrintf("<input type=hidden " "name=\"bantest\" " "value=\"1\">\n"); // // end yippy parms // // display the turing test so they can unban themselves g_turingTest.printTest(testBuf); testBuf->safePrintf("<br><center><input type=submit " "value=\"submit\"></center><br>"); testBuf->safePrintf("</form>"); } return false; checkSubstr: // sanity! if ( justCheck ) { char *xx=NULL;*xx=0; } // Look for regular expressions that may serve as a signature of // a botnet attack char *banRegex = g_conf.m_banRegex; long banRegexLen = g_conf.m_banRegexLen; if (!banRegex || !banRegexLen) return true; // Don't do regex...look for comma-separated lists of substrings long start = 0; bool gotMatch = false; bool missedMatch = false; for (long i=0;i<= banRegexLen;i++) { if (i != banRegexLen && banRegex[i] && banRegex[i] != '\n' && banRegex[i] != '\r' && banRegex[i] != ',') continue; char c = banRegex[i]; // NULL terminate banRegex[i] = '\0'; // search for substr (must be longer than 2 chars if ( i - start > 2){ if (strnstr(reqStr, reqLen, &banRegex[start])) gotMatch = true; else missedMatch = true; } banRegex[i] = c; start = i+1; // check the next substr if we're not at the // end of line or end of buffer if (c != '\n' && c != '\r' && c != '\0') continue; // did we get all the substrings? if (gotMatch && !missedMatch) return false; // reset for the next set of substrings gotMatch = false; missedMatch = false; } return true; }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno) { // seccomp, caps, private, user namespace if (strcmp(ptr, "noroot") == 0) { check_user_namespace(); return 0; } else if (strcmp(ptr, "seccomp") == 0) { arg_seccomp = 1; return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps_default_filter = 1; return 0; } else if (strcmp(ptr, "caps.drop all") == 0) { arg_caps_drop_all = 1; return 0; } else if (strcmp(ptr, "shell none") == 0) { arg_shell_none = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } else if (strcmp(ptr, "private-dev") == 0) { arg_private_dev = 1; return 0; } else if (strcmp(ptr, "nogroups") == 0) { arg_nogroups = 1; return 0; } else if (strcmp(ptr, "netfilter") == 0) { arg_netfilter = 1; return 0; } else if (strncmp(ptr, "netfilter ", 10) == 0) { arg_netfilter = 1; arg_netfilter_file = strdup(ptr + 10); if (!arg_netfilter_file) errExit("strdup"); check_netfilter_file(arg_netfilter_file); return 0; } // seccomp drop list on top of default list if (strncmp(ptr, "seccomp ", 8) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list = strdup(ptr + 8); if (!arg_seccomp_list) errExit("strdup"); #endif return 0; } // seccomp drop list without default list if (strncmp(ptr, "seccomp.drop ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list_drop = strdup(ptr + 13); if (!arg_seccomp_list_drop) errExit("strdup"); #endif return 0; } // seccomp keep list if (strncmp(ptr, "seccomp.keep ", 13) == 0) { arg_seccomp = 1; #ifdef HAVE_SECCOMP arg_seccomp_list_keep= strdup(ptr + 13); if (!arg_seccomp_list_keep) errExit("strdup"); #endif return 0; } // caps drop list if (strncmp(ptr, "caps.drop ", 10) == 0) { arg_caps_drop = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // caps keep list if (strncmp(ptr, "caps.keep ", 10) == 0) { arg_caps_keep = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; if (atoip(ptr + 4, &dns)) { fprintf(stderr, "Error: invalid DNS server IP address\n"); return 1; } if (cfg.dns1 == 0) cfg.dns1 = dns; else if (cfg.dns2 == 0) cfg.dns2 = dns; else if (cfg.dns3 == 0) cfg.dns3 = dns; else { fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); return 1; } return 0; } // cpu affinity if (strncmp(ptr, "cpu ", 4) == 0) { read_cpu_list(ptr + 4); return 0; } // cgroup if (strncmp(ptr, "cgroup ", 7) == 0) { set_cgroup(ptr + 7); return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; fs_check_private_dir(); arg_private = 1; return 0; } // private list of files and directories if (strncmp(ptr, "private.keep ", 13) == 0) { cfg.home_private_keep = ptr + 13; fs_check_home_list(); arg_private = 1; return 0; } // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: mising second directory for bind\n"); exit(1); } // check directories check_file_name(dname1, lineno); check_file_name(dname2, lineno); if (strstr(dname1, "..") || strstr(dname2, "..")) { fprintf(stderr, "Error: invalid file name.\n"); exit(1); } // insert comma back *(dname2 - 1) = ','; return 1; } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { ptr += 14; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { ptr += 18; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "tmpfs ", 6) == 0) ptr += 6; else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames check_file_name(ptr, lineno); if (strstr(ptr, "..")) { if (lineno == 0) fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } return 1; }
void UrlParser::parse() { // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] const char *urlEnd = m_url + m_urlLen; const char *currentPos = m_url; // hier-part = "//" authority path-abempty // / path-absolute // / path-rootless // / path-empty const char *authorityPos = static_cast<const char*>( memmem( currentPos, urlEnd - currentPos, "//", 2 ) ); if ( authorityPos != NULL ) { if ( authorityPos != currentPos ) { m_scheme = currentPos; m_schemeLen = authorityPos - currentPos - 1; } m_authority = authorityPos + 2; currentPos = m_authority; } else { m_authority = currentPos; } const char *pathPos = static_cast<const char*>( memchr( currentPos, '/', urlEnd - currentPos ) ); if ( pathPos != NULL ) { m_authorityLen = pathPos - m_authority; currentPos = pathPos + 1; } else { m_authorityLen = urlEnd - m_authority; // nothing else to process return; } // @todo similar logic in Url.cpp ( merge this ) // authority = [ userinfo "@" ] host [ ":" port ] const char *userInfoPos = static_cast<const char *>( memchr( m_authority, '@', m_authorityLen ) ); if ( userInfoPos != NULL ) { m_host = userInfoPos + 1; m_hostLen = m_authorityLen - ( userInfoPos - m_authority ) - 1; } else { m_host = m_authority; m_hostLen = m_authorityLen; } const char *portPos = static_cast<const char *>( memrchr( m_host, ':', m_hostLen ) ); if ( portPos != NULL ) { m_hostLen -= ( m_hostLen - ( portPos - m_host ) ); } // host = IP-literal / IPv4address / reg-name /// @todo ALC we should remove the const cast once we fix all the const issue int32_t ip = atoip( m_host, m_hostLen ); if ( ip ) { int32_t domainLen = 0; m_domain = getDomainOfIp ( const_cast<char *>( m_host ), m_hostLen , &domainLen ); m_domainLen = domainLen; } else { const char *tldPos = ::getTLD( const_cast<char *>( m_host ), m_hostLen ); if ( tldPos ) { size_t tldLen = m_host + m_hostLen - tldPos; if ( tldLen < m_hostLen ) { m_domain = static_cast<const char *>( memrchr( m_host, '.', m_hostLen - tldLen - 1 ) ); if ( m_domain ) { m_domain += 1; m_domainLen = m_hostLen - ( m_domain - m_host ); } else { m_domain = m_host; m_domainLen = m_hostLen; } } } } const char *queryPos = static_cast<const char*>( memchr( currentPos, '?', urlEnd - currentPos ) ); if ( queryPos != NULL ) { currentPos = queryPos + 1; } const char *anchorPos = static_cast<const char*>( memrchr( currentPos, '#', urlEnd - currentPos ) ); // if ( anchorPos != NULL ) { // currentPos = anchorPos + 1; // } const char *pathEnd = queryPos ? queryPos : (anchorPos ? anchorPos : urlEnd); m_pathEndChar = *( pathEnd - 1 ); const char *queryEnd = anchorPos ? anchorPos : urlEnd; // path const char *prevPos = pathPos + 1; while ( prevPos && ( prevPos <= pathEnd ) ) { size_t len = pathEnd - prevPos; currentPos = strnpbrk( prevPos, len, "/;&" ); if ( currentPos ) { len = currentPos - prevPos; } UrlComponent urlPart = UrlComponent( UrlComponent::TYPE_PATH, prevPos, len, *( prevPos - 1 ) ); m_paths.push_back( urlPart ); prevPos = currentPos ? currentPos + 1 : NULL; } // query if ( queryPos ) { prevPos = queryPos + 1; bool isPrevAmpersand = false; while ( prevPos && ( prevPos < queryEnd ) ) { size_t len = queryEnd - prevPos; currentPos = strnpbrk( prevPos, len, "&;" ); if ( currentPos ) { len = currentPos - prevPos; } UrlComponent urlPart = UrlComponent( UrlComponent::TYPE_QUERY, prevPos, len, *( prevPos - 1 ) ); std::string key = urlPart.getKey(); // check previous urlPart if ( isPrevAmpersand ) { urlPart.setSeparator( '&' ); } bool isAmpersand = ( !urlPart.hasValue() && urlPart.getKey() == "amp" ); if ( !key.empty() && !isAmpersand ) { // we don't cater for case sensitive query parameter (eg: parm, Parm, PARM is assumed to be the same) auto it = m_queriesMap.find( key ); if (it == m_queriesMap.end()) { m_queries.push_back( urlPart ); m_queriesMap[key] = m_queries.size() - 1; } else { m_queries[it->second] = urlPart; } } prevPos = currentPos ? currentPos + 1 : NULL; isPrevAmpersand = isAmpersand; } } }
void Blaster::startBlastering(){ long long now=gettimeofdayInMilliseconds(); if(m_print && m_totalDone>0 && (m_totalDone % 20)==0){ log("blaster: Processed %li urls in %li ms",m_totalDone, (long) (now-m_startTime)); m_print=false; } //Launch the maximum number of threads that are allowed while ( m_p1 < m_p1end && m_launched < m_maxNumThreads && m_totalUrls){ // clear any error g_errno = 0; // make a new state StateBD *st; try { st = new (StateBD); } catch ( ... ) { g_errno = ENOMEM; log("blaster: Failed. " "Could not allocate %li bytes for query. " "Returning HTTP status of 500.", (long)sizeof(StateBD)); return; } mnew ( st , sizeof(StateBD) , "BlasterDiff3" ); st->m_buf1=NULL; m_totalUrls--; // make into a url class. Set both u1 and u2 here. //st->m_u1.set ( m_p1 , gbstrlen(m_p1) ); st->m_u1 = m_p1; // skip to next url m_p1 += gbstrlen ( m_p1 ) + 1; if (m_blasterDiff){ //st->m_u2.set ( m_p2 , gbstrlen(m_p2) ); st->m_u2 = m_p2; m_p2 += gbstrlen ( m_p2 ) + 1; } // log(LOG_WARN,"\n"); log(LOG_WARN,"blaster: Downloading %s",st->m_u1); // set port if port switch is true //if ( m_portSwitch ) { // long r = rand() % 32; // u.setPort ( 8000 + r ); //} // count it m_launched++; long ip=0; long port=0; if (m_useProxy){ ip=atoip("66.154.102.20",13); port=3128; } // get it bool status = g_httpServer.getDoc ( st->m_u1 , // url 0, // ip 0 , // offset -1 , // size 0 , // ifModifiedSince st , // state gotDocWrapper1, // callback 60*1000, // timeout ip, port, 30*1024*1024, //maxLen 30*1024*1024); // continue if it blocked if ( ! status ) continue; // If not blocked, there is an error. m_launched--; // log msg log("From file1, got doc1 %s: %s", st->m_u1 , mstrerror(g_errno) ); // we gotta wait break; } // bail if not done yet //if ( m_launched > 0 ) return; if (m_totalUrls) return; //otherwise return if launched have not come back if (m_launched) return; // exit now // g_conf.save(); // closeALL(NULL,NULL); exit ( 0 ); }
bool Msg7::inject ( TcpSocket *s , HttpRequest *r , void *state , void (*callback)(void *state)) { // save socket // socket is responsible for free the HTTP request, which contains // the POSTed content, so if he gets destroyed we have to make sure // we no longer reference that content. m_socket = s; long contentLen; // get the junk char *coll = r->getString ( "c" , NULL , NULL /*default*/); if ( ! coll ) coll = "main"; bool quickReply = r->getLong ( "quick" , 0 ); //char *pwd = r->getString ( "pwd" , NULL ); char *url = r->getString ( "u" , NULL , NULL /*default*/); bool recycleContent = r->getLong ( "recycle",0); char *ips = r->getString ( "ip" , NULL , NULL ); //char *username = g_users.getUsername(r); long firstIndexed = r->getLongLong("firstindexed",0LL); long lastSpidered = r->getLongLong("lastspidered",0LL); long hopCount = r->getLong("hopcount",-1); long newOnly = r->getLong("newonly",0); long charset = r->getLong("charset",-1); long deleteIt = r->getLong("delete",0); char hasMime = r->getLong("hasmime",0); // do consistency testing? bool doConsistencyTesting = r->getLong("dct",0); // default spiderlinks to no for injects long spiderLinks = r->getLong("spiderlinks",0); long forcedIp = 0; if ( ips ) forcedIp = atoip ( ips , gbstrlen(ips) ); char *content = r->getString ( "content" , &contentLen , NULL ); // mark doesn't like to url-encode his content if ( ! content ) { content = r->getUnencodedContent (); contentLen = r->getUnencodedContentLen (); //contentIsEncoded = false; } // we do not want the parser every holding up a query really long niceness = 1; // tell xmldoc to download the doc if ( contentLen == 0 ) content = NULL; // the http request gets freed if this blocks, so we have to // copy the content!!! if ( content ) { m_contentAllocSize = contentLen + 1; m_content = mdup ( content , contentLen + 1 , "injcont" ); } else { m_content = NULL; m_contentAllocSize = 0; } return inject ( url, forcedIp, m_content, contentLen, recycleContent, CT_HTML, // contentType, coll, quickReply , NULL,//username , NULL,//pwd, niceness, state, callback, firstIndexed, lastSpidered, hopCount, newOnly, charset, spiderLinks, deleteIt, hasMime, doConsistencyTesting); }
void process_opt_str(char *line, char *lastarg, option_block *opts) { char *delim; int sze; while(*line != 0) { /* used: beslnqrtpvfh XRSTUOLVD */ switch(*line++) { case 'b': opts->start_test = atoi(lastarg); break; case 'e': opts->stop_on_fail = 1; break; case 's': opts->no_sequence_fuzz = 0; opts->no_literal_fuzz = 1; break; case 'l': opts->no_literal_fuzz = 0; opts->no_sequence_fuzz = 1; break; case 'n': opts->new_logfile = 1; break; case 'q': opts->verbosity = QUIET; break; case 'X': opts->hexl_dump = 1; break; case 'r': opts->trim_nl = 1; break; case 'R': opts->forget_conn = 1; break; case 'S': opts->host = atoip(lastarg); strncpy(opts->host_spec, lastarg, MAX_HOSTSPEC_SIZE); opts->host_spec[MAX_HOSTSPEC_SIZE-1] = 0; break; case 't': opts->time_out = atoi(lastarg); break; case 'p': opts->port = atoi(lastarg); strncpy(opts->port_spec, lastarg, MAX_PORTSPEC_SIZE); opts->port_spec[MAX_PORTSPEC_SIZE-1] = 0; break; case 'T': opts->tcp_flag = 1; break; case 'U': opts->udp_flag = 1; break; case 'O': opts->out_flag = 1; break; case 'L': strncpy(opts->pLogFilename, lastarg, MAX_FILENAME_SIZE-1); opts->pLogFilename[MAX_FILENAME_SIZE-1] = 0; break; case 'v': /*when I put in better logging.*/ opts->verbosity = VERBOSE; break; case 'f': strncpy(opts->pFilename, lastarg, MAX_FILENAME_SIZE-1); opts->pFilename[MAX_FILENAME_SIZE-1] = 0; break; case 'h': print_help(); exit(0); break; case 'V': print_version(); exit(0); break; case 'D': delim = strstr(lastarg, "="); if(delim == NULL) { fprintf(stderr, "error: delimiter not found for symbol.\n"); exit(-1); } sze = strlen(delim+1); if(sze == 0) { fprintf(stderr, "error: symbol's value is null.\n"); exit(-1); } add_symbol(lastarg, (delim - lastarg), delim+1, sze, opts, 0); break; default: printf("unknown option: %c\n", *line); exit(0); } } }
// check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands // return 0 if the command was already executed inside the function int profile_check_line(char *ptr, int lineno, const char *fname) { EUID_ASSERT(); // check ignore list int i; for (i = 0; i < MAX_PROFILE_IGNORE; i++) { if (cfg.profile_ignore[i] == NULL) break; if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0) return 0; // ignore line } if (strncmp(ptr, "ignore ", 7) == 0) { char *str = strdup(ptr + 7); if (*str == '\0') { fprintf(stderr, "Error: invalid ignore option\n"); exit(1); } // find an empty entry in profile_ignore array int j; for (j = 0; j < MAX_PROFILE_IGNORE; j++) { if (cfg.profile_ignore[j] == NULL) break; } if (j >= MAX_PROFILE_IGNORE) { fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); exit(1); } // ... and configure it else cfg.profile_ignore[j] = str; return 0; } // mkdir if (strncmp(ptr, "mkdir ", 6) == 0) { fs_mkdir(ptr + 6); return 0; } // sandbox name else if (strncmp(ptr, "name ", 5) == 0) { cfg.name = ptr + 5; if (strlen(cfg.name) == 0) { fprintf(stderr, "Error: invalid sandbox name\n"); exit(1); } return 0; } else if (strcmp(ptr, "ipc-namespace") == 0) { arg_ipc = 1; return 0; } // seccomp, caps, private, user namespace else if (strcmp(ptr, "noroot") == 0) { #if HAVE_USERNS if (checkcfg(CFG_USERNS)) check_user_namespace(); else fprintf(stderr, "Warning: user namespace feature is disabled in Firejail configuration file\n"); #endif return 0; } else if (strcmp(ptr, "nonewprivs") == 0) { arg_nonewprivs = 1; return 0; } else if (strcmp(ptr, "seccomp") == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) arg_seccomp = 1; else fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); #endif return 0; } else if (strcmp(ptr, "caps") == 0) { arg_caps_default_filter = 1; return 0; } else if (strcmp(ptr, "caps.drop all") == 0) { arg_caps_drop_all = 1; return 0; } else if (strcmp(ptr, "shell none") == 0) { arg_shell_none = 1; return 0; } else if (strcmp(ptr, "tracelog") == 0) { arg_tracelog = 1; return 0; } else if (strcmp(ptr, "private") == 0) { arg_private = 1; return 0; } else if (strcmp(ptr, "private-dev") == 0) { arg_private_dev = 1; return 0; } else if (strcmp(ptr, "private-tmp") == 0) { arg_private_tmp = 1; return 0; } else if (strcmp(ptr, "nogroups") == 0) { arg_nogroups = 1; return 0; } else if (strcmp(ptr, "nosound") == 0) { arg_nosound = 1; arg_private_dev = 1; return 0; } else if (strcmp(ptr, "netfilter") == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) arg_netfilter = 1; else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "netfilter ", 10) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netfilter = 1; arg_netfilter_file = strdup(ptr + 10); if (!arg_netfilter_file) errExit("strdup"); check_netfilter_file(arg_netfilter_file); } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "netfilter6 ", 11) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_netfilter6 = 1; arg_netfilter6_file = strdup(ptr + 11); if (!arg_netfilter6_file) errExit("strdup"); check_netfilter_file(arg_netfilter6_file); } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strcmp(ptr, "net none") == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { arg_nonetwork = 1; cfg.bridge0.configured = 0; cfg.bridge1.configured = 0; cfg.bridge2.configured = 0; cfg.bridge3.configured = 0; cfg.interface0.configured = 0; cfg.interface1.configured = 0; cfg.interface2.configured = 0; cfg.interface3.configured = 0; } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "net ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { #ifdef HAVE_NETWORK_RESTRICTED // compile time restricted networking if (getuid() != 0) { fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); exit(1); } #endif // run time restricted networking if (checkcfg(CFG_RESTRICTED_NETWORK) && getuid() != 0) { fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n"); exit(1); } if (strcmp(ptr + 4, "lo") == 0) { fprintf(stderr, "Error: cannot attach to lo device\n"); exit(1); } Bridge *br; if (cfg.bridge0.configured == 0) br = &cfg.bridge0; else if (cfg.bridge1.configured == 0) br = &cfg.bridge1; else if (cfg.bridge2.configured == 0) br = &cfg.bridge2; else if (cfg.bridge3.configured == 0) br = &cfg.bridge3; else { fprintf(stderr, "Error: maximum 4 network devices are allowed\n"); exit(1); } net_configure_bridge(br, ptr + 4); } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "iprange ", 8) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->iprange_start || br->iprange_end) { fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n"); exit(1); } // parse option arguments char *firstip = ptr + 8; char *secondip = firstip; while (*secondip != '\0') { if (*secondip == ',') break; secondip++; } if (*secondip == '\0') { fprintf(stderr, "Error: invalid IP range\n"); exit(1); } *secondip = '\0'; secondip++; // check addresses if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) || br->iprange_start >= br->iprange_end) { fprintf(stderr, "Error: invalid IP range\n"); exit(1); } if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) { fprintf(stderr, "Error: IP range addresses not in network range\n"); exit(1); } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } // from here else if (strncmp(ptr, "mac ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (mac_not_zero(br->macsandbox)) { fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); exit(1); } // read the address if (atomac(ptr + 4, br->macsandbox)) { fprintf(stderr, "Error: invalid MAC address\n"); exit(1); } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "mtu ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { fprintf(stderr, "Error: invalid mtu value\n"); exit(1); } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "ip ", 3) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->arg_ip_none || br->ipsandbox) { fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); exit(1); } // configure this IP address for the last bridge defined if (strcmp(ptr + 3, "none") == 0) br->arg_ip_none = 1; else { if (atoip(ptr + 3, &br->ipsandbox)) { fprintf(stderr, "Error: invalid IP address\n"); exit(1); } } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "ip6 ", 4) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { Bridge *br = last_bridge_configured(); if (br == NULL) { fprintf(stderr, "Error: no network device configured\n"); exit(1); } if (br->arg_ip_none || br->ip6sandbox) { fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); exit(1); } // configure this IP address for the last bridge defined // todo: verify ipv6 syntax br->ip6sandbox = ptr + 4; // if (atoip(argv[i] + 5, &br->ipsandbox)) { // fprintf(stderr, "Error: invalid IP address\n"); // exit(1); // } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } else if (strncmp(ptr, "defaultgw ", 10) == 0) { #ifdef HAVE_NETWORK if (checkcfg(CFG_NETWORK)) { if (atoip(ptr + 10, &cfg.defaultgw)) { fprintf(stderr, "Error: invalid IP address\n"); exit(1); } } else fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); #endif return 0; } if (strncmp(ptr, "protocol ", 9) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) protocol_store(ptr + 9); else fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); #endif return 0; } if (strncmp(ptr, "env ", 4) == 0) { env_store(ptr + 4); return 0; } // seccomp drop list on top of default list if (strncmp(ptr, "seccomp ", 8) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list = strdup(ptr + 8); if (!cfg.seccomp_list) errExit("strdup"); } else fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); #endif return 0; } // seccomp drop list without default list if (strncmp(ptr, "seccomp.drop ", 13) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list_drop = strdup(ptr + 13); if (!cfg.seccomp_list_drop) errExit("strdup"); } else fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); #endif return 0; } // seccomp keep list if (strncmp(ptr, "seccomp.keep ", 13) == 0) { #ifdef HAVE_SECCOMP if (checkcfg(CFG_SECCOMP)) { arg_seccomp = 1; cfg.seccomp_list_keep= strdup(ptr + 13); if (!cfg.seccomp_list_keep) errExit("strdup"); } else fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); #endif return 0; } // caps drop list if (strncmp(ptr, "caps.drop ", 10) == 0) { arg_caps_drop = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // caps keep list if (strncmp(ptr, "caps.keep ", 10) == 0) { arg_caps_keep = 1; arg_caps_list = strdup(ptr + 10); if (!arg_caps_list) errExit("strdup"); // verify seccomp list and exit if problems if (caps_check_list(arg_caps_list, NULL)) exit(1); return 0; } // hostname if (strncmp(ptr, "hostname ", 9) == 0) { cfg.hostname = ptr + 9; return 0; } // dns if (strncmp(ptr, "dns ", 4) == 0) { uint32_t dns; if (atoip(ptr + 4, &dns)) { fprintf(stderr, "Error: invalid DNS server IP address\n"); return 1; } if (cfg.dns1 == 0) cfg.dns1 = dns; else if (cfg.dns2 == 0) cfg.dns2 = dns; else if (cfg.dns3 == 0) cfg.dns3 = dns; else { fprintf(stderr, "Error: up to 3 DNS servers can be specified\n"); return 1; } return 0; } // cpu affinity if (strncmp(ptr, "cpu ", 4) == 0) { read_cpu_list(ptr + 4); return 0; } // nice value if (strncmp(ptr, "nice ", 4) == 0) { cfg.nice = atoi(ptr + 5); if (getuid() != 0 &&cfg.nice < 0) cfg.nice = 0; arg_nice = 1; return 0; } // cgroup if (strncmp(ptr, "cgroup ", 7) == 0) { set_cgroup(ptr + 7); return 0; } // writable-etc if (strcmp(ptr, "writable-etc") == 0) { if (cfg.etc_private_keep) { fprintf(stderr, "Error: private-etc and writable-etc are mutually exclusive\n"); exit(1); } arg_writable_etc = 1; return 0; } // writable-var if (strcmp(ptr, "writable-var") == 0) { arg_writable_var = 1; return 0; } // private directory if (strncmp(ptr, "private ", 8) == 0) { cfg.home_private = ptr + 8; fs_check_private_dir(); arg_private = 1; return 0; } // private /etc list of files and directories if (strncmp(ptr, "private-etc ", 12) == 0) { if (arg_writable_etc) { fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n"); exit(1); } cfg.etc_private_keep = ptr + 12; fs_check_etc_list(); arg_private_etc = 1; return 0; } // private /bin list of files if (strncmp(ptr, "private-bin ", 12) == 0) { cfg.bin_private_keep = ptr + 12; arg_private_bin = 1; fs_check_bin_list(); return 0; } // filesystem bind if (strncmp(ptr, "bind ", 5) == 0) { #ifdef HAVE_BIND if (checkcfg(CFG_BIND)) { if (getuid() != 0) { fprintf(stderr, "Error: --bind option is available only if running as root\n"); exit(1); } // extract two directories char *dname1 = ptr + 5; char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories if (dname2 == NULL) { fprintf(stderr, "Error: missing second directory for bind\n"); exit(1); } // check directories invalid_filename(dname1); invalid_filename(dname2); if (strstr(dname1, "..") || strstr(dname2, "..")) { fprintf(stderr, "Error: invalid file name.\n"); exit(1); } if (is_link(dname1) || is_link(dname2)) { fprintf(stderr, "Symbolic links are not allowed for bind command\n"); exit(1); } // insert comma back *(dname2 - 1) = ','; return 1; } else { fprintf(stderr, "Warning: bind feature is disabled in Firejail configuration file\n"); return 0; } #else return 0; #endif } // rlimit if (strncmp(ptr, "rlimit", 6) == 0) { if (strncmp(ptr, "rlimit-nofile ", 14) == 0) { ptr += 14; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nofile); arg_rlimit_nofile = 1; } else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_nproc); arg_rlimit_nproc = 1; } else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { ptr += 13; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_fsize); arg_rlimit_fsize = 1; } else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { ptr += 18; if (not_unsigned(ptr)) { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } sscanf(ptr, "%u", &cfg.rlimit_sigpending); arg_rlimit_sigpending = 1; } else { fprintf(stderr, "Invalid rlimit option on line %d\n", lineno); exit(1); } return 0; } // read-write if (strncmp(ptr, "read-write ", 11) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: read-write command is available only for root user\n"); exit(1); } fs_rdwr_add(ptr + 11); return 0; } // rest of filesystem if (strncmp(ptr, "blacklist ", 10) == 0) ptr += 10; else if (strncmp(ptr, "blacklist-nolog ", 16) == 0) ptr += 16; else if (strncmp(ptr, "noblacklist ", 12) == 0) ptr += 12; else if (strncmp(ptr, "whitelist ", 10) == 0) { #ifdef HAVE_WHITELIST if (checkcfg(CFG_WHITELIST)) { arg_whitelist = 1; ptr += 10; } else return 0; #else return 0; #endif } else if (strncmp(ptr, "read-only ", 10) == 0) ptr += 10; else if (strncmp(ptr, "tmpfs ", 6) == 0) { if (getuid() != 0) { fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n"); exit(1); } ptr += 6; } else { if (lineno == 0) fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr); else if (fname != NULL) fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } // some characters just don't belong in filenames invalid_filename(ptr); if (strstr(ptr, "..")) { if (lineno == 0) fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); else if (fname != NULL) fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname); else fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); exit(1); } return 1; }
int cliIpRouteCidrCmd(CliMode mode, int argc, char **argv) { char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // extract data uint32_t ip; uint32_t mask; if (atocidr(argv[2], &ip, &mask)) { strcpy(data, "Error: invalid IP address\n"); return RCPERR; } // this should be a network address if (ip & (~mask)) { strcpy(data, "Error: invalid IP address\n"); return RCPERR; } uint32_t gw; if (atoip(argv[3], &gw)) { strcpy(data, "Error: invalid next hop address\n"); return RCPERR; } uint32_t metric = 1; if (argc == 5) metric = atoi(argv[4]); // test RIP distance if (metric == RCP_ROUTE_DISTANCE_RIP) { sprintf(data, "Error: Administrative distance %d is reserved for RIP\n", RCP_ROUTE_DISTANCE_RIP); return RCPERR; } // test OSPF distance if (metric == RCP_ROUTE_DISTANCE_OSPF) { sprintf(data, "Error: Administrative distance %d is reserved for OSPF\n", RCP_ROUTE_DISTANCE_OSPF); return RCPERR; } // add the route RcpStaticRoute *rt; if ((rt = shm_find_route_static(ip, mask, gw)) != NULL) { // a route is already present in the kernel with a different metric // delete the old route first rcpDelRoute(muxsock, ip, mask, gw); rcpLog(muxsock, RCP_PROC_ROUTER, RLOG_INFO, RLOG_FC_ROUTER, "static route %d.%d.%d.%d/%d gateway %d.%d.%d.%d deleted", RCP_PRINT_IP(ip), mask2bits(mask), RCP_PRINT_IP(gw)); redistribute_route(SIOCDELRT, ip, mask, gw, rt->metric); rt->metric = metric; strcpy(data, "Warning: route replaced\n"); } else if ((rt = shm_find_route_static(ip, mask, 0)) != NULL && rt->metric == metric) { // we are in an equal cost multipath (ECMP) case - not supported yet! // delete the old route first rcpDelRoute(muxsock, rt->ip, rt->mask, rt->gw); rcpLog(muxsock, RCP_PROC_ROUTER, RLOG_INFO, RLOG_FC_ROUTER, "static route %d.%d.%d.%d/%d gateway %d.%d.%d.%d deleted", RCP_PRINT_IP(ip), mask2bits(mask), RCP_PRINT_IP(gw)); redistribute_route(SIOCDELRT, ip, mask, gw, rt->metric); rt->gw = gw; strcpy(data, "Warning: existing route with a different destination deleted\n"); } else { // create a new route rt = shm_find_route_empty(); if (rt == NULL) { sprintf(data, "Error: cannot add route, limit reached\n"); return RCPERR; } memset(rt, 0, sizeof(RcpStaticRoute)); rt->ip = ip; rt->mask = mask; rt->gw = gw; rt->metric = metric; rt->valid = 1; rt->type = RCP_ROUTE_STATIC; } rcpAddRoute(muxsock, RCP_ROUTE_STATIC, ip, mask, gw, metric); redistribute_route(SIOCADDRT, ip, mask, gw, metric); return 0; }