void CSecurity::Serialize(CArchive& ar) { int nVersion = SECURITY_SER_VERSION; if ( ar.IsStoring() ) { ar << nVersion; ar << m_bDenyPolicy; ar.WriteCount( GetCount() ); for ( POSITION pos = GetIterator() ; pos ; ) { GetNext( pos )->Serialize( ar, nVersion ); } // Unimplemented //for ( CAddressRuleMap::const_iterator i = m_pIPRules.begin() ; i != m_pIPRules.end() ; ++i ) //{ // (*i).second->Serialize( ar, nVersion ); //} } else // Loading { Clear(); ar >> nVersion; ar >> m_bDenyPolicy; const DWORD tNow = static_cast< DWORD >( time( NULL ) ); for ( DWORD_PTR nCount = ar.ReadCount() ; nCount > 0 ; nCount-- ) { CSecureRule* pRule = new CSecureRule( FALSE ); pRule->Serialize( ar, nVersion ); if ( pRule->IsExpired( tNow, TRUE ) ) { delete pRule; continue; } // Special handling for single-IP security rules if ( pRule->m_nType == CSecureRule::srAddress && pRule->m_nAction == CSecureRule::srDeny && *(DWORD*)pRule->m_nMask == 0xffffffff ) { SetAddressMap( *(DWORD*)pRule->m_nIP, SetRuleIndex( pRule ) ); continue; } if ( pRule->m_nType == CSecureRule::srContentHash && pRule->m_nAction == CSecureRule::srDeny ) { SetHashMap( pRule->GetContentWords(), SetRuleIndex( pRule ) ); continue; } if ( pRule->m_nType == CSecureRule::srExternal ) ListLoader.AddList( pRule ); m_pRules.AddTail( pRule ); } } }
void CListLoader::OnRun() { while ( IsThreadEnabled() && m_pQueue.GetCount() ) { CSecureRule* pRule = m_pQueue.GetHead(); if ( ! pRule || ! pRule->m_pContent || pRule->m_nType != CSecureRule::srExternal ) { m_pQueue.RemoveHead(); continue; } CString strPath = pRule->GetContentWords(); if ( strPath.GetLength() < 6 ) { m_pQueue.RemoveHead(); continue; } CString strCommentBase = pRule->m_sComment; if ( strCommentBase.IsEmpty() ) strCommentBase = _T("• %u"); else if ( strCommentBase.ReverseFind( _T('•') ) >= 0 ) strCommentBase = strCommentBase.Left( strCommentBase.ReverseFind( _T('•') ) + 1 ) + _T(" %u"); else strCommentBase += _T(" • %u"); if ( strPath[1] != _T(':') ) strPath = Settings.General.DataPath + strPath; CFile pFile; if ( ! pFile.Open( (LPCTSTR)strPath.GetBuffer(), CFile::modeRead ) ) { m_pQueue.RemoveHead(); continue; } const BYTE nIndex = Security.SetRuleIndex( pRule ); try { CBuffer pBuffer; const DWORD nLength = pFile.GetLength(); pBuffer.EnsureBuffer( nLength ); pBuffer.m_nLength = nLength; pFile.Read( pBuffer.m_pBuffer, nLength ); pFile.Close(); // Format: Delineated Lists CString strLine, strURN; DWORD nCount = 0; int nPos; //TIMER_START while ( pBuffer.ReadLine( strLine ) && IsThreadEnabled() && pRule ) { strLine.TrimRight(); if ( strLine.GetLength() < 7 ) continue; // Blank/Invalid line if ( strLine[ 0 ] == '#' ) { if ( strLine[ strLine.GetLength() - 1 ] == _T(':') && strLine.Find( _T("urn:") ) > 0 ) strURN = strLine.Mid( strLine.Find( _T("urn:") ) ); // Default "# urn:type:" continue; // Comment line } if ( strLine[ 0 ] < '0' || strLine[ 0 ] > 'z' ) // Whitespace/Chars continue; // Invalid line if ( ++nCount % 10 == 0 ) { if ( pRule->m_sComment.IsEmpty() ) strCommentBase = _T("• %u"); else if ( pRule->m_sComment.ReverseFind( _T('•') ) < 0 ) strCommentBase = pRule->m_sComment + _T(" • %u"); pRule->m_sComment.Format( strCommentBase, nCount ); Sleep( 1 ); // Limit CPU } // Hashes: if ( ( ! strURN.IsEmpty() && strLine.Find( _T('.'), 5 ) < 0 ) || StartsWith( strLine, _PT("urn:") ) ) { nPos = strLine.FindOneOf( _T(" \t") ); if ( nPos > 0 ) strLine.Truncate( nPos ); // Trim at whitespace (remove any trailing comments) if ( ! strURN.IsEmpty() && ! StartsWith( strLine, _PT("urn:") ) ) strLine = strURN + strLine; // Default "urn:type:" prepended if ( strLine.GetLength() > 35 ) Security.SetHashMap( strLine, nIndex ); else nCount--; continue; } // IPs: nPos = strLine.ReverseFind( _T(':') ); if ( nPos > 0 ) strLine = strLine.Mid( nPos + 1 ); // Remove leading comment for some formats nPos = strLine.FindOneOf( _T(" \t") ); if ( nPos > 0 ) strLine.Truncate( nPos ); // Trim at whitespace (remove any trailing comments) if ( strLine.GetLength() < 7 || strLine.Find( _T('.') ) < 1 ) { nCount--; continue; } nPos = strLine.Find( _T('-') ); // Possible Range if ( nPos < 0 ) // Single IP { Security.SetAddressMap( IPStringToDWORD( strLine, TRUE ), nIndex ); continue; } CString strFirst = strLine.Left( nPos ); CString strLast = strLine.Mid( nPos + 1 ); if ( strFirst == strLast ) { Security.SetAddressMap( IPStringToDWORD( strLine, TRUE ), nIndex ); continue; } // inet_addr( CT2CA( (LPCTSTR)strLast ) DWORD nFirst = IPStringToDWORD( strFirst, FALSE ); DWORD nLast = IPStringToDWORD( strLast, FALSE ); if ( nFirst < 10 || nFirst >= 0xE0000000 ) // 0 or "0.0." or "224-255" continue; // Redundant/Invalid //if ( Network.IsReserved( (IN_ADDR*)nFirst ) ) // Crash //if ( StartsWith( strFirst, _PT("0.0") ) || // StartsWith( strFirst, _PT("6.0") ) || // StartsWith( strFirst, _PT("7.0") ) || // StartsWith( strFirst, _PT("11.0") ) || // StartsWith( strFirst, _PT("55.0") ) || // StartsWith( strFirst, _PT("127.0") ) ) // continue; // Redundant for ( DWORD nRange = Settings.Security.ListRangeLimit ; nFirst <= nLast && nRange ; nFirst++, nRange-- ) { Security.SetAddressMap( htonl( nFirst ), nIndex ); // Reverse host-byte order } } if ( pRule ) pRule->m_sComment.Format( strCommentBase, nCount ); // Final update PostMainWndMessage( WM_SANITY_CHECK ); //TIMER_STOP } catch ( CException* pException ) { if ( pFile.m_hFile != CFile::hFileNull ) pFile.Close(); // File is still open so close it pException->Delete(); } m_pQueue.RemoveHead(); // Done } Exit(); Wakeup(); Sleep( 5000 ); // Recheck if ( ! m_pQueue.GetCount() ) // && IsThreadEnabled() { CQuickLock oLock( Security.m_pSection ); Security.m_Cache.clear(); PostMainWndMessage( WM_SANITY_CHECK ); } }