Esempio n. 1
0
def main() -> int:
    dumpconf = 'dumpconf'
    initdb = 'initdb'
    parser = argparse.ArgumentParser()
    parser.add_argument('action',
                        choices=[dumpconf, initdb, 'refresh'],
                        help='Action to perform')
    parser.add_argument('-c',
                        '--conf',
                        default=None,
                        help='Configuration file')
    parser.add_argument('-f',
                        '--force',
                        default=False,
                        action='store_true',
                        help='Force action (default: False)')
    args = parser.parse_args()
    if not config.init(args.conf):
        log.error(f'Cannot parse configuration file: {args.conf}')
        sys.exit(1)
    if dumpconf == args.action:
        config.write(sys.stdout)
    elif initdb == args.action:
        RefreshLog.init(create_all=True)
    else:
        ClamavRefresh(args).refresh_all()
    return 0
Esempio n. 2
0
 def setUp(self) -> None:
     super().setUp()
     RefreshLog.init(create_all=True)
     self.s = RefreshLog._session()
     self.s.query(RefreshLog).delete()
     self.s.add(RefreshLog(ID1))
     self.s.commit()
Esempio n. 3
0
 def setUp(self) -> None:
     super().setUp()
     self.ci = _ClamavTestItem(url=URL1, section=self.UNITTEST, option='option', path='path')
     RefreshLog.init()
     self.s = RefreshLog._session()
     self.s.query(RefreshLog).delete()
     self.s.add(RefreshLog(self.ci, DIGEST_DUMMY))
     self.s.commit()
Esempio n. 4
0
 def test_cleanup2(self):
     file = tempfile.NamedTemporaryFile(mode='w+t', encoding='utf-8', delete=False)
     file.write(self.UNITTEST)
     file.close()
     provider = uuid.uuid4().hex
     self.ci.section = provider
     self.ci.path = file.name
     self.ci.url = URL2
     self.s.add(RefreshLog(self.ci, DIGEST_DUMMY))
     self.s.commit()
     self.assertEqual(1, RefreshLog.cleanup_provider(provider))
Esempio n. 5
0
 def setUp(self) -> None:
     super().setUp()
     RefreshLog.init()
     self.s = RefreshLog._session()
     self.s.query(RefreshLog).delete()
     cia = _ClamavTestItem('spam', 'option', 'a', path='a')
     cib = _ClamavTestItem('spamalot', 'option', 'b', path='b')
     self.s.add(RefreshLog(cia, 'dummy'))
     self.s.add(RefreshLog(cib, 'dummy'))
     self.s.commit()
     self.s.commit()
Esempio n. 6
0
 def test_refresh_age(self):
     r = RefreshLog(URL_SHA256)
     r.updated += timedelta(minutes=10)
     self.s.add(r)
     self.s.commit()
     ci = _CI(self.UNITTEST, 'x', URL_SHA256, 'sha256', f'{self.TMPDIR}/x')
     self.assertFalse(self.ref.refresh(ci))
Esempio n. 7
0
 def test_refresh_digest_match(self):
     ci = _ClamavTestItem(self.UNITTEST, 'x', URL_MD5, 'md5',
                          f'{self.TMPDIR}/x')
     r = RefreshLog(ci, DIGEST_MD5)
     self.s.add(r)
     self.s.commit()
     self.assertFalse(self.ref.refresh(ci))
Esempio n. 8
0
 def test_url_blank(self):
     ci = _ClamavTestItem('unittest4', 'url_blank', '', 'md5',
                          f'{self.TMPDIR}/blank')
     self.s.add(RefreshLog(ci, DIGEST_DUMMY))
     self.s.commit()
     n = self.ref.refresh_all()
     self.assertEqual(3, n)
Esempio n. 9
0
 def test_refresh(self):
     ci = _ClamavTestItem(self.UNITTEST, 'x', URL_MD5, 'md5',
                          f'{self.TMPDIR}/x')
     self.s.add(RefreshLog(ci, DIGEST_DUMMY))
     self.s.commit()
     n = self.ref.refresh_all()
     self.assertEqual(3, n)
Esempio n. 10
0
 def test_refresh_age(self):
     ci = _ClamavTestItem(self.UNITTEST, 'x', URL_SHA256, 'sha256',
                          f'{self.TMPDIR}/x')
     r = RefreshLog(ci, DIGEST_DUMMY)
     r.updated += timedelta(minutes=10)
     self.s.add(r)
     self.s.commit()
     self.assertFalse(self.ref.refresh(ci))
Esempio n. 11
0
    def refresh(self, ci: ClamavItem) -> bool:
        """Refresh a single ClamAV item.

        :param ci: Item to refresh.
        :return: True if new payload data was written, False otherwise.
        """
        try:
            if self.args.force:
                log.debug(f'{ci.url} refresh forced')
            elif not RefreshLog.is_outdated(ci.url, ci.interval):
                log.debug(f'{ci.url} below max age')
                return False
            digest = get_digest(ci)
            if not digest.ok:
                return False
            if digest.data and RefreshLog.digest_matches(ci.url, digest.data):
                log.debug(f'{ci.url} unchanged')
                RefreshLog.update(ci.url, digest.data)  # Update timestamp
                return False
            payload = get_payload(ci)
            if not payload.ok:
                return False
            integrity = check_integrity(payload.data, ci.check, digest.data)
            if not integrity.ok:
                log.warning(f'{ci.url} {integrity.data}')
                return False
            with open(ci.path, 'wb') as f:
                size = f.write(payload.data)
                log.info(f'{ci.path} updated ({size} bytes)')
                RefreshLog.update(ci.url, digest.data)  # Update digest and timestamp
        except OSError as e:  # pragma: no cover
            log.exception(e)
        return True
Esempio n. 12
0
 def setUp(self) -> None:
     super().setUp()
     RefreshLog.init()
     self.s = RefreshLog._session()
     self.s.query(RefreshLog).delete()
     self.s.commit()
Esempio n. 13
0
 def test_match_one(self):
     x = RefreshLog.url_path_mappings('^spam$')
     self.assertEqual(1, len(x))
Esempio n. 14
0
 def test_refresh(self):
     self.s.add(RefreshLog(URL_MD5))
     self.s.commit()
     n = self.ref.refresh_all()
     self.assertEqual(3, n)
Esempio n. 15
0
 def cleanup_providers() -> int:
     count = 0
     for section in config.sections():
         if config.auto_cleanup(section) and not config.is_enabled(section):
             count += RefreshLog.cleanup_provider(section)
     return count
Esempio n. 16
0
 def test_duplicate(self):
     self.s.add(RefreshLog(ID1))
     with self.assertRaises(IntegrityError):
         self.s.commit()
Esempio n. 17
0
 def test_duplicate(self):
     self.s.add(RefreshLog(self.ci, DIGEST_DUMMY))
     with self.assertRaises(IntegrityError):
         self.s.commit()
Esempio n. 18
0
 def test_insert(self):
     self.s.add(RefreshLog(ID2))
     self.s.commit()
     self.assertTrue(True)  # Must not raise an exception
Esempio n. 19
0
 def test_stamp2(self):
     RefreshLog.update(ID2, 'XXX')  # Must not raise an exception
     self.assertTrue(True)
Esempio n. 20
0
 def test_cleanup1(self):
     self.assertEqual(0, RefreshLog.cleanup_provider(self.UNKNOWN))
Esempio n. 21
0
 def test_match_none(self):
     x = RefreshLog.url_path_mappings('ham')
     self.assertEqual(0, len(x))
Esempio n. 22
0
 def test_insert(self):
     self.ci.url = URL2
     self.s.add(RefreshLog(self.ci, DIGEST_DUMMY))
     self.s.commit()
     self.assertTrue(True)  # Must not raise an exception
Esempio n. 23
0
 def test_refresh_required(self):
     self.assertTrue(RefreshLog.is_outdated(URL1, 0))
Esempio n. 24
0
 def print_url_path_mappings(self, outfile) -> None:
     r: RefreshLog
     for r in RefreshLog.url_path_mappings(self.args.provider):
         print(f'{r.provider}\t{r.url}\t{r.path}', file=outfile)
Esempio n. 25
0
 def test_stamp1(self):
     RefreshLog.update(self.ci, DIGEST_DUMMY)  # Must not raise an exception
     self.assertTrue(True)
Esempio n. 26
0
 def test_missing_path(self):
     self.ci.path = None
     self.s.add(RefreshLog(self.ci, DIGEST_DUMMY))
     with self.assertRaises(IntegrityError):
         self.s.commit()
Esempio n. 27
0
 def test_match_two(self):
     x = RefreshLog.url_path_mappings('spam')
     self.assertEqual(2, len(x))