ERRCODE Config::load( std::string filename, bool createnew ) { std::ifstream configfile; std::string lineinput, category( "Global" ), item, value; ERRCODE ret = OZ_OK; if( isloaded()) clear(); configfile.open( filename.c_str()); if( !configfile.is_open()) { if( FileExists( filename ) || !createnew ) { returncode( OZ_INI_FAILED_TO_OPEN ); } else { return( create( filename )); } } m_isloaded = true; while( configfile.good()) { std::getline( configfile, lineinput ); trim( lineinput ); if( matchcategory( lineinput, category )) { } else if( matchline( lineinput, item, value )) { if(( ret = set( category + ":" + item, value )) != 0 ) { configfile.close(); m_isloaded = false; returncode( ret ); } } } configfile.close(); m_configfilename = filename; returncode( OZ_OK ); }
ERRCODE Config::save() { std::ofstream configfile; std::string setcategory( "Global" ), item, category; dictionaryiterator itemiterator; if( !isloaded()) returncode( OZ_INI_NO_DICT ); configfile.open( m_configfilename.c_str()); if( !configfile.is_open()) returncode( OZ_INI_FAILED_TO_WRITE ); for( itemiterator = m_dictionary.begin(); itemiterator != m_dictionary.end(); ++itemiterator ) { if( splitkey( itemiterator->first, category, item )) { if( setcategory != category ) { setcategory = category; configfile << "[" << category << "]" << std::endl; } configfile << item << " = " << itemiterator->second << "\n"; } else { configfile << itemiterator->first << " = " << itemiterator->second << std::endl; } } configfile.close(); returncode( OZ_OK ); }
ERRCODE Config::clear() { if( !isloaded()) returncode( OZ_INI_NO_DICT ); m_dictionary.clear(); m_isloaded = false; m_configfilename = ""; returncode( OZ_OK ); }
ERRCODE Config::create( std::string filename, bool overwrite ) { if( isloaded()) clear(); if( FileExists( filename ) && !overwrite) { returncode( OZ_INI_FILE_EXISTS ); } m_configfilename = filename; m_isloaded = true; returncode( OZ_OK ); }
// check data received from ICAP server and interpret as virus name & return value int icapinstance::doScan(Socket & icapsock, HTTPHeader * docheader, const char* object, unsigned int objectsize, NaughtyFilter * checkme) { char *data = new char[8192]; try { String line; int rc = icapsock.getLine(data, 8192, o.content_scanner_timeout); if (rc == 0) return ICAP_NODATA; line = data; #ifdef DGDEBUG std::cout << "reply from icap: " << line << std::endl; #endif // reply is of the format: // ICAP/1.0 204 No Content Necessary (etc) String returncode(line.after(" ").before(" ")); if (returncode == "204") { #ifdef DGDEBUG std::cerr << "ICAP says clean!" << std::endl; #endif delete[]data; return DGCS_CLEAN; } else if (returncode == "100") { #ifdef DGDEBUG std::cerr << "ICAP says continue!" << std::endl; #endif // discard rest of headers (usually just a blank line) // this is so we are in the right place in the data stream to // call doScan() again later, because people like Symantec seem // to think sending code 100 then code 204 one after the other // is not an abuse of the ICAP specification. while (icapsock.getLine(data, 8192, o.content_scanner_timeout) > 0) { if (data[0] == 13) break; } delete[]data; return ICAP_CONTINUE; } else if (returncode == "200") { #ifdef DGDEBUG std::cerr << "ICAP says maybe not clean!" << std::endl; #endif while (icapsock.getLine(data, 8192, o.content_scanner_timeout) > 0) { if (data[0] == 13) // end marker break; line = data; // Symantec's engine gives us the virus name in the ICAP headers if (supportsXIF && line.startsWith("X-Infection-Found")) { #ifdef DGDEBUG std::cout << "ICAP says infected! (X-Infection-Found)" << std::endl; #endif lastvirusname = line.after("Threat=").before(";"); delete[]data; blockFile(NULL,NULL,checkme); return DGCS_INFECTED; } } // AVIRA's Antivir gives us 200 in all cases, so // - unfortunately - we must pay attention to the encapsulated // header/body. if (needsBody) { // grab & compare the HTTP return code from modified response // if it's been modified, assume there's an infection icapsock.getLine(data, 8192, o.content_scanner_timeout); line = data; #ifdef DGDEBUG std::cout << "Comparing original return code to modified:" << std::endl << docheader->header.front() << std::endl << line << std::endl; #endif int respmodReturnCode = line.after(" ").before(" ").toInteger(); if (respmodReturnCode != docheader->returnCode()) { #ifdef DGDEBUG std::cerr << "ICAP says infected! (returned header comparison)" << std::endl; #endif delete[] data; lastvirusname = "Unknown"; blockFile(NULL,NULL,checkme); return DGCS_INFECTED; } // ok - headers were identical, so look at encapsulated body // discard the rest of the encapsulated headers while (icapsock.getLine(data, 8192, o.content_scanner_timeout) > 0) { if (data[0] == 13) break; } // grab body chunk size #ifdef DGDEBUG std::cout << "Comparing original body data to modified" << std::endl; #endif icapsock.getLine(data, 8192, o.content_scanner_timeout); line = data; int bodysize = line.hexToInteger(); // get, say, the first 100 bytes and compare them to what we // originally sent to see if it has been modified unsigned int chunksize = (bodysize < 100) ? bodysize : 100; if (chunksize > objectsize) chunksize = objectsize; icapsock.readFromSocket(data, chunksize, 0, o.content_scanner_timeout); if (memcmp(data, object, chunksize) == 0) { #ifdef DGDEBUG std::cerr << "ICAP says clean!" << std::endl; #endif delete[]data; return DGCS_CLEAN; } else { #ifdef DGDEBUG std::cerr << "ICAP says infected! (body byte comparison)" << std::endl; #endif delete[] data; lastvirusname = "Unknown"; blockFile(NULL,NULL,checkme); return DGCS_INFECTED; } } // even if we don't find an X-Infection-Found header, // the file is still infected! #ifdef DGDEBUG std::cerr << "ICAP says infected! (no further tests)" << std::endl; #endif delete[] data; lastvirusname = "Unknown"; blockFile(NULL,NULL,checkme); return DGCS_INFECTED; } else if (returncode == "404") { #ifdef DGDEBUG std::cerr << "ICAP says no such service!" << std::endl; #endif lastmessage = "ICAP reports no such service"; syslog(LOG_ERR, "ICAP reports no such service; check your server URL"); delete[]data; return DGCS_SCANERROR; } else { #ifdef DGDEBUG std::cerr << "ICAP returned unrecognised response code: " << returncode << std::endl; #endif lastmessage = "ICAP returned unrecognised response code."; syslog(LOG_ERR, "ICAP returned unrecognised response code: %s", returncode.toCharArray()); delete[]data; return DGCS_SCANERROR; } delete[]data; } catch(std::exception & e) { #ifdef DGDEBUG std::cerr << "Exception getting reply from ICAP: " << e.what() << std::endl; #endif lastmessage = "Exception getting reply from ICAP."; syslog(LOG_ERR, "Exception getting reply from ICAP: %s", e.what()); delete[]data; return DGCS_SCANERROR; } // it is generally NOT a good idea, when using virus scanning, // to continue as if nothing went wrong by default! return DGCS_SCANERROR; }
ERRCODE Config::set( std::string item, std::string value ) { if( !isloaded()) returncode( OZ_INI_NO_DICT ); m_dictionary[ item ] = value; returncode( OZ_OK ); }