// Test whether or not a particular request's incoming/outgoing data should be scanned. // This is an early-stage (request headers only) test; no other info is known about // the actual data itself when this is called. int CSPlugin::willScanRequest(const String &url, const char *user, int filtergroup, const char *ip, bool post, bool reconstituted, bool exception, bool bypass) { // Most content scanners only deal with original, unmodified content if (reconstituted) { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring reconstituted data" << std::endl; #endif return DGCS_NOSCAN; } // Deal with POST file uploads conditionally, but subject only to the "scanpost" // option, not to the domain & URL lists - uploading files does not have the same // implications as downlaoding them. if (post) { if (scanpost) { #ifdef DGDEBUG std::cout << "willScanRequest: I'm interested in uploads" << std::endl; #endif return DGCS_NEEDSCAN; } else { #ifdef DGDEBUG std::cout << "willScanRequest: Not interested in uploads" << std::endl; #endif return DGCS_NOSCAN; } } String urld(HTTPHeader::decode(url)); urld.removeWhiteSpace(); urld.toLower(); urld.removePTP(); String domain, tempurl, foundurl, path; unsigned int fl; if (urld.contains("/")) { domain = urld.before("/"); path = "/" + urld.after("/"); path.hexDecode(); path.realPath(); } else { domain = urld; } // Don't scan the web server which hosts the access denied page if (((o.fg[filtergroup]->reporting_level == 1) || (o.fg[filtergroup]->reporting_level == 2)) && domain.startsWith(o.fg[filtergroup]->access_denied_domain)) { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring our own webserver" << std::endl; #endif return DGCS_NOSCAN; } // exceptionvirussitelist tempurl = domain; while (tempurl.contains(".")) { if (exceptionvirussitelist.findInList(tempurl.toCharArray()) != NULL) { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring exception virus site" << std::endl; #endif return DGCS_NOSCAN; // exact match } tempurl = tempurl.after("."); // check for being in higher level domains } if (tempurl.length() > 1) { // allows matching of .tld tempurl = "." + tempurl; if (exceptionvirussitelist.findInList(tempurl.toCharArray()) != NULL) { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring exception virus site" << std::endl; #endif return DGCS_NOSCAN; // exact match } } // exceptionvirusurllist tempurl = domain + path; if (tempurl.endsWith("/")) { tempurl.chop(); // chop off trailing / if any } while (tempurl.before("/").contains(".")) { char *i = exceptionvirusurllist.findStartsWith(tempurl.toCharArray()); if (i != NULL) { foundurl = i; fl = foundurl.length(); if (tempurl.length() > fl) { unsigned char c = tempurl[fl]; if (c == '/' || c == '?' || c == '&' || c == '=') { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring exception virus URL" << std::endl; #endif return DGCS_NOSCAN; // matches /blah/ or /blah/foo but not /blahfoo } } else { #ifdef DGDEBUG std::cout << "willScanRequest: ignoring exception virus URL" << std::endl; #endif return DGCS_NOSCAN; // exact match } } tempurl = tempurl.after("."); // check for being in higher level domains } #ifdef DGDEBUG std::cout << "willScanRequest: I'm interested" << std::endl; #endif return DGCS_NEEDSCAN; }
// Test whether or not a particular request's incoming/outgoing data should be scanned. // This is a later-stage test; info is known about the actual data itself when this is called. int CSPlugin::willScanData(const String &url, const char *user, int filtergroup, const char *ip, bool post, bool reconstituted, bool exception, bool bypass, const String &disposition, const String &mimetype, off_t size) { //exceptionvirusmimetypelist if (mimetype.length() > 2) { if (exceptionvirusmimetypelist.findInList(mimetype.toCharArray()) != NULL) { #ifdef DGDEBUG std::cout << "willScanData: ignoring exception MIME type (" << mimetype.c_str() << ")" << std::endl; #endif return DGCS_NOSCAN; // match } } //exceptionvirusextensionlist String extension; if (disposition.length() > 2) { // If we have a content-disposition, determine file extension from that #ifdef DGDEBUG std::cout << "disposition: " << disposition << std::endl; #endif std::string::size_type start = disposition.find("filename="); if (start != std::string::npos) { start += 9; char endchar = ';'; if (disposition[start] == '"') { endchar = '"'; ++start; } std::string::size_type end = disposition.find(endchar, start); if (end != std::string::npos) extension = disposition.substr(start, end - start); else extension = disposition.substr(start); } while (extension.contains(".")) { extension = extension.after("."); } extension = "." + extension; #ifdef DGDEBUG std::cout << "extension from disposition: " << extension << std::endl; #endif } else { // Otherwise, determine it from the URL String urld(HTTPHeader::decode(url)), path; urld.removeWhiteSpace(); urld.toLower(); urld.removePTP(); if (urld.contains("/")) { path = urld.after("/"); path.hexDecode(); path.realPath(); } if (!path.contains("?")) { extension = path; } else if (mimetype.contains("application/")) { extension = path; if (extension.contains("?")) { extension = extension.before("?"); } } #ifdef DGDEBUG std::cout << "extension from URL: " << extension << std::endl; #endif } if (extension.contains(".")) { if (exceptionvirusextensionlist.findEndsWith(extension.toCharArray()) != NULL) { #ifdef DGDEBUG std::cout << "willScanData: ignoring exception file extension (" << extension.c_str() << ")" << std::endl; #endif return DGCS_NOSCAN; // match } } #ifdef DGDEBUG std::cout << "willScanData: I'm interested" << std::endl; #endif return DGCS_NEEDSCAN; }
// test whether or not a request should be scanned based on sent & received headers int CSPlugin::scanTest(HTTPHeader * requestheader, HTTPHeader * docheader, const char *user, int filtergroup, const char *ip) { char *i; //exceptionvirusmimetypelist String mimetype(docheader->getContentType()); #ifdef DGDEBUG std::cout<<"mimetype: "<<mimetype<<std::endl; #endif i = exceptionvirusmimetypelist.findInList(mimetype.toCharArray()); if (i != NULL) { return DGCS_NOSCAN; // match } String disposition(docheader->disposition()); #ifdef DGDEBUG std::cout<<"disposition: "<<disposition<<std::endl; #endif String url(requestheader->url()); String urld(requestheader->decode(url)); urld.removeWhiteSpace(); urld.toLower(); urld.removePTP(); String domain, tempurl, foundurl, path, extension; unsigned int fl; if (urld.contains("/")) { domain = urld.before("/"); path = "/" + urld.after("/"); path.hexDecode(); path.realPath(); } else { domain = urld; } // don't scan our web server if (((o.fg[filtergroup]->reporting_level == 1) || (o.fg[filtergroup]->reporting_level == 2)) && domain.startsWith(o.fg[filtergroup]->access_denied_domain)) { return DGCS_NOSCAN; } //exceptionvirusextensionlist if (disposition.length() > 2) { extension = disposition; while (extension.contains(".")) { extension = extension.after("."); } extension = "." + extension; } else { if (!path.contains("?")) { extension = path; } else if (mimetype.contains("application/")) { extension = path; if (extension.contains("?")) { extension = extension.before("?"); } } } #ifdef DGDEBUG std::cout<<"extension: "<<extension<<std::endl; #endif if (extension.contains(".")) { i = exceptionvirusextensionlist.findEndsWith(extension.toCharArray()); if (i != NULL) { return DGCS_NOSCAN; // match } } // exceptionvirussitelist tempurl = domain; #ifdef DGDEBUG std::cout<<"domain: "<<domain<<std::endl; #endif while (tempurl.contains(".")) { i = exceptionvirussitelist.findInList(tempurl.toCharArray()); if (i != NULL) { return DGCS_NOSCAN; // exact match } tempurl = tempurl.after("."); // check for being in higher level domains } if (tempurl.length() > 1) { // allows matching of .tld tempurl = "." + tempurl; i = exceptionvirussitelist.findInList(tempurl.toCharArray()); if (i != NULL) { return DGCS_NOSCAN; // exact match } } // exceptionvirusurllist tempurl = domain + path; if (tempurl.endsWith("/")) { tempurl.chop(); // chop off trailing / if any } while (tempurl.before("/").contains(".")) { i = exceptionvirusurllist.findStartsWith(tempurl.toCharArray()); if (i != NULL) { foundurl = i; fl = foundurl.length(); if (tempurl.length() > fl) { unsigned char c = tempurl[fl]; if (c == '/' || c == '?' || c == '&' || c == '=') { return DGCS_NOSCAN; // matches /blah/ or /blah/foo but not /blahfoo } } else { return DGCS_NOSCAN; // exact match } } tempurl = tempurl.after("."); // check for being in higher level domains } #ifdef DGDEBUG std::cout << "URL " << url << " is going to need AV scanning." << std::endl; #endif return DGCS_NEEDSCAN; }