server: check virustotal has APK before uploading it

This restructures the virustotal uploading so that first checks whether
virustotal already has the file, and only if not does it upload it.  This
also handles the public API rate limiting, which returns an HTTP 204. This
will now try again until it succeeds, even when rate limited.   Instead of
just getting the list of files from the filesystem, this reads the index-v1
which also already has the SHA256 in there.  virustotal also uses SHA256 as
a unique ID for files.
This commit is contained in:
Hans-Christoph Steiner 2017-04-12 00:23:41 +02:00
parent 8dd9d63e8f
commit d74d6160dd

View file

@ -24,6 +24,7 @@ import paramiko
import pwd import pwd
import re import re
import subprocess import subprocess
import time
from argparse import ArgumentParser from argparse import ArgumentParser
import logging import logging
import shutil import shutil
@ -401,18 +402,50 @@ def upload_to_android_observatory(repo_section):
def upload_to_virustotal(repo_section, vt_apikey): def upload_to_virustotal(repo_section, vt_apikey):
import json
import requests import requests
if repo_section == 'repo': logging.getLogger("urllib3").setLevel(logging.WARNING)
for f in glob.glob(os.path.join(repo_section, '*.apk')): logging.getLogger("requests").setLevel(logging.WARNING)
fpath = f
fname = os.path.basename(f)
logging.info('Uploading ' + fname + ' to virustotal.com')
# upload the file with a post request if repo_section == 'repo':
params = {'apikey': vt_apikey} with open(os.path.join(repo_section, 'index-v1.json')) as fp:
files = {'file': (fname, open(fpath, 'rb'))} index = json.load(fp)
r = requests.post('https://www.virustotal.com/vtapi/v2/file/scan', files=files, params=params) for packageName, packages in index['packages'].items():
for package in packages:
filename = package['apkName']
repofilename = os.path.join(repo_section, filename)
logging.info('Uploading ' + repofilename + ' to virustotal.com')
headers = {
"User-Agent": "F-Droid"
}
params = {
'apikey': vt_apikey,
'resource': package['hash'],
}
download = False
while True:
r = requests.post('https://www.virustotal.com/vtapi/v2/file/report',
params=params, headers=headers)
if r.status_code == 200:
response = r.json()
if response['response_code'] == 0:
download = True
elif response['positives'] > 0:
logging.warning(repofilename + ' has been flagged by virustotal '
+ str(response['positives']) + 'times:'
+ '\n\t' + response['permalink'])
break
elif r.status_code == 204:
time.sleep(10) # wait for public API rate limiting
if download:
files = {
'file': (filename, open(repofilename, 'rb'))
}
r = requests.post('https://www.virustotal.com/vtapi/v2/file/scan',
params=params, headers=headers, files=files)
response = r.json() response = r.json()
logging.info(response['verbose_msg'] + " " + response['permalink']) logging.info(response['verbose_msg'] + " " + response['permalink'])