add json output to analyze.py via the -j flag

This commit is contained in:
Julien Vehent 2014-10-11 19:37:08 -04:00
parent 0da92f25b7
commit b846ac9d5b
1 changed files with 38 additions and 15 deletions

View File

@ -7,6 +7,8 @@
import sys, os, json, subprocess, logging, argparse, platform import sys, os, json, subprocess, logging, argparse, platform
from collections import namedtuple from collections import namedtuple
from datetime import datetime
from copy import deepcopy
# is_fubar assumes that a configuration is not completely messed up # is_fubar assumes that a configuration is not completely messed up
# and looks for reasons to think otherwise. it will return True if # and looks for reasons to think otherwise. it will return True if
@ -253,49 +255,67 @@ def is_ordered(results, ref_ciphersuite, lvl):
return ordered return ordered
def evaluate_all(results): def evaluate_all(results):
status = "obscure unknown ssl" status = "obscure or unknown"
if len(results['ciphersuite']) == 0: if len(results['ciphersuite']) == 0:
return "no ssl" return "no"
if is_modern(results): if is_modern(results):
status = "modern tls" status = "modern"
if not is_ordered(results, modern_ciphers, "modern"): if not is_ordered(results, modern_ciphers, "modern"):
status = "modern tls with bad ordering" status = "modern with bad ordering"
if is_intermediate(results): if is_intermediate(results):
status = "intermediate tls" status = "intermediate"
if not is_ordered(results, intermediate_ciphers, "intermediate"): if not is_ordered(results, intermediate_ciphers, "intermediate"):
status = "intermediate tls with bad ordering" status = "intermediate with bad ordering"
if is_old(results): if is_old(results):
status = "old ssl" status = "old"
if not is_ordered(results, old_ciphers, "old"): if not is_ordered(results, old_ciphers, "old"):
status = "old ssl with bad ordering" status = "old with bad ordering"
if is_fubar(results): if is_fubar(results):
status = "bad ssl" status = "bad"
return status return status
def process_results(data, level=None): def process_results(data, level=None, do_json=False):
results = dict() results = dict()
# initialize the failures struct # initialize the failures struct
global failures global failures
json_output = dict()
failures = dict() failures = dict()
failures['fubar'] = [] failures['fubar'] = []
failures['old'] = [] failures['old'] = []
failures['intermediate'] = [] failures['intermediate'] = []
failures['modern'] = [] failures['modern'] = []
if not level:
level='none'
try: try:
results = json.loads(data) results = json.loads(data)
except ValueError, e: except ValueError, e:
print("invalid json data") print("invalid json data")
try: try:
if results: if results:
print(results['target'] + " has " + evaluate_all(results)) if do_json:
json_output['target'] = results['target']
d = datetime.utcnow()
json_output['utctimestamp'] = d.isoformat("T") + "Z"
json_output['level'] = evaluate_all(results)
json_output['target_level'] = level
json_output['compliance'] = False
if json_output['level'] == json_output['target_level']:
json_output['compliance'] = True
else:
print(results['target'] + " has " + evaluate_all(results) + " ssl/tls")
except TypeError, e: except TypeError, e:
pass return False
if do_json:
json_output['failures'] = deepcopy(failures)
print json.dumps(json_output)
return True
if len(failures['fubar']) > 0: if len(failures['fubar']) > 0:
print("\nThings that are really FUBAR:") print("\nThings that are really FUBAR:")
@ -303,7 +323,7 @@ def process_results(data, level=None):
print("* " + failure) print("* " + failure)
# print failures # print failures
if level: if level != 'none':
if len(failures[level]) > 0: if len(failures[level]) > 0:
print("\nChanges needed to match the " + level + " level:") print("\nChanges needed to match the " + level + " level:")
for failure in failures[level]: for failure in failures[level]:
@ -314,6 +334,7 @@ def process_results(data, level=None):
print("\nChanges needed to match the " + lvl + " level:") print("\nChanges needed to match the " + lvl + " level:")
for failure in failures[lvl]: for failure in failures[lvl]:
print("* " + failure) print("* " + failure)
return True
def build_ciphers_lists(opensslbin): def build_ciphers_lists(opensslbin):
global all_ciphers, old_ciphers, intermediate_ciphers, modern_ciphers, errors global all_ciphers, old_ciphers, intermediate_ciphers, modern_ciphers, errors
@ -388,6 +409,8 @@ def main():
help='analyze a <target>, invokes cipherscan') help='analyze a <target>, invokes cipherscan')
parser.add_argument('-o', dest='openssl', parser.add_argument('-o', dest='openssl',
help='path to openssl binary, if you don\'t like the default') help='path to openssl binary, if you don\'t like the default')
parser.add_argument('-j', dest='json', action='store_true',
help='output results in json format')
args = parser.parse_args() args = parser.parse_args()
if args.debug: if args.debug:
@ -405,7 +428,7 @@ def main():
data = subprocess.check_output(['./cipherscan', '-o', args.openssl, '-j', args.target]) data = subprocess.check_output(['./cipherscan', '-o', args.openssl, '-j', args.target])
else: else:
data = subprocess.check_output(['./cipherscan', '-j', args.target]) data = subprocess.check_output(['./cipherscan', '-j', args.target])
process_results(data, args.level) process_results(data, args.level, args.json)
else: else:
if os.fstat(args.infile.fileno()).st_size < 2: if os.fstat(args.infile.fileno()).st_size < 2:
logging.error("invalid input file") logging.error("invalid input file")
@ -413,7 +436,7 @@ def main():
sys.exit(1) sys.exit(1)
data = args.infile.readline() data = args.infile.readline()
logging.debug('Evaluating results from stdin: ' + data) logging.debug('Evaluating results from stdin: ' + data)
process_results(data, args.level) process_results(data, args.level, args.json)
if __name__ == "__main__": if __name__ == "__main__":
main() main()