| 1 |
#!/usr/bin/env python
|
| 2 |
#
|
| 3 |
# generate bug report content for a given package name
|
| 4 |
# and a number of CVE ids
|
| 5 |
#
|
| 6 |
# you could use it for example in combination with the
|
| 7 |
# following shell function:
|
| 8 |
# report-vuln(){
|
| 9 |
# TMPFILE="$HOME/reportbug.tmp"
|
| 10 |
# $HOME/debian/svn/secure-testing/bin/report-vuln "$@" > $TMPFILE
|
| 11 |
# mutt -i $TMPFILE submit@bugs.debian.org
|
| 12 |
# rm $TMPFILE
|
| 13 |
# }
|
| 14 |
# export http_proxy if you need to use an http proxy to report bugs
|
| 15 |
|
| 16 |
import sys, re, urllib, os
|
| 17 |
|
| 18 |
def gen_index(ids):
|
| 19 |
ret = ''
|
| 20 |
for cnt, id in enumerate(ids):
|
| 21 |
ret += '\n[' + str(cnt) + '] http://cve.mitre.org/cgi-bin/cvename.cgi?name=' + id + '\n'
|
| 22 |
ret += ' http://security-tracker.debian.org/tracker/' + id
|
| 23 |
|
| 24 |
return ret
|
| 25 |
|
| 26 |
def http_get(id):
|
| 27 |
param = urllib.urlencode({'name' : id})
|
| 28 |
resp = ''
|
| 29 |
try:
|
| 30 |
f = urllib.urlopen('http://cve.mitre.org/cgi-bin/cvename.cgi?%s' % param)
|
| 31 |
resp = f.read()
|
| 32 |
except Exception, e:
|
| 33 |
error('on doing HTTP request' + str(e))
|
| 34 |
|
| 35 |
f.close()
|
| 36 |
|
| 37 |
return resp
|
| 38 |
|
| 39 |
# this is a hack that parses the cve id description from mitre
|
| 40 |
def get_cve(id):
|
| 41 |
desc = False
|
| 42 |
r = re.compile('.*<th\ colspan=.*>Description<.*')
|
| 43 |
tag = re.compile('.*</?tr>.*')
|
| 44 |
ret = ''
|
| 45 |
resp = http_get(id)
|
| 46 |
|
| 47 |
for line in resp.rsplit('\n'):
|
| 48 |
if r.match(line):
|
| 49 |
desc = True
|
| 50 |
continue
|
| 51 |
|
| 52 |
if tag.match(line) and desc:
|
| 53 |
continue
|
| 54 |
|
| 55 |
if desc and '<td colspan="2">' in line:
|
| 56 |
ret += '| ' + re.sub('.*<td colspan="2">', '', line)
|
| 57 |
continue
|
| 58 |
|
| 59 |
if desc and '</td>' in line:
|
| 60 |
break
|
| 61 |
|
| 62 |
if desc and line != '':
|
| 63 |
ret = ret + '\n| ' + line
|
| 64 |
|
| 65 |
return ret + '\n'
|
| 66 |
|
| 67 |
def gen_text(pkg, cveid):
|
| 68 |
vuln_suff = 'y'
|
| 69 |
cve_suff = ''
|
| 70 |
time_w = 'was'
|
| 71 |
|
| 72 |
if len(cveid) > 1:
|
| 73 |
cve_suff = 's'
|
| 74 |
vuln_suff = 'ies'
|
| 75 |
time_w = 'were'
|
| 76 |
|
| 77 |
header = '''Package: %s
|
| 78 |
Version: FILLINAFFECTEDVERSION
|
| 79 |
Severity: FILLINSEVERITY
|
| 80 |
Tags: security
|
| 81 |
|
| 82 |
Hi,
|
| 83 |
the following CVE (Common Vulnerabilities & Exposures) id%s %s
|
| 84 |
published for %s.
|
| 85 |
''' % (pkg, cve_suff, time_w, pkg)
|
| 86 |
|
| 87 |
footer = '''If you fix the vulnerabilit%s please also make sure to include the
|
| 88 |
CVE id%s in your changelog entry.
|
| 89 |
|
| 90 |
For further information see:''' % (vuln_suff, cve_suff)
|
| 91 |
|
| 92 |
print header
|
| 93 |
for cnt, cve in enumerate(cveid):
|
| 94 |
print cve + '[' + str(cnt) + ']:'
|
| 95 |
print get_cve(cve)
|
| 96 |
|
| 97 |
print footer
|
| 98 |
print gen_index(cveid)
|
| 99 |
|
| 100 |
def error(msg):
|
| 101 |
print 'error: ' + msg
|
| 102 |
sys.exit(1)
|
| 103 |
|
| 104 |
def usage():
|
| 105 |
print sys.argv[0], '<pkg> <cve id(s)>'
|
| 106 |
sys.exit(0)
|
| 107 |
|
| 108 |
def main():
|
| 109 |
if len(sys.argv) < 3:
|
| 110 |
usage()
|
| 111 |
|
| 112 |
pkg = sys.argv[1]
|
| 113 |
cve = sys.argv[2:]
|
| 114 |
|
| 115 |
# check for valid parameters
|
| 116 |
p = re.compile('^[a-z].*')
|
| 117 |
c = re.compile('(CVE|cve)\-[0-9]{4}-[0-9]{4}')
|
| 118 |
|
| 119 |
if not p.match(pkg):
|
| 120 |
error(pkg + ' does not seem to be a valid source package name')
|
| 121 |
|
| 122 |
for arg in cve:
|
| 123 |
if not c.match(arg):
|
| 124 |
error(arg + ' does not seem to be a valid CVE id')
|
| 125 |
|
| 126 |
gen_text(pkg, cve)
|
| 127 |
|
| 128 |
if __name__ == '__main__':
|
| 129 |
main()
|