syntribos/syntribos/checks/length.py

110 lines
3.7 KiB
Python

# Copyright 2016 Rackspace
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
import syntribos.signal
CONF = cfg.CONF
def percentage_difference(test):
"""Validates length of two responses
Compares the length of a fuzzed response with a response to the
baseline request. If the response is longer than expected, returns
a `LengthPercentageDiffSignal`
:returns: SynSignal or None
"""
check_name = "LENGTH_DIFF"
data = {
"req1": test.init_req,
"req2": test.test_req,
"resp1": test.init_resp,
"resp2": test.test_resp,
"req1_len": len(test.init_req.body or ""),
"req2_len": len(test.test_req.body or ""),
"resp1_len": len(test.init_resp.content or ""),
"resp2_len": len(test.test_resp.content or ""),
}
data["req_diff"] = data["req2_len"] - data["req1_len"]
data["resp_diff"] = data["resp2_len"] - data["resp1_len"]
data["percent_diff"] = abs(
float(data["resp_diff"]) / (data["resp1_len"] + 1)) * 100
data["dir"] = "UNDER" if data["resp1_len"] > data["resp2_len"] else "OVER"
if data["resp1_len"] == data["resp2_len"]:
# No difference in response lengths
return None
elif data["req_diff"] == data["resp_diff"]:
# Response difference accounted for by difference in request lengths
return None
elif data["percent_diff"] < CONF.test.length_diff_percent:
# Difference not larger than configured percentage
return None
text = (
"Validate Length:\n"
"\tRequest 1 length: {0}\n"
"\tResponse 1 length: {1}\n"
"\tRequest 2 length: {2}\n"
"\tResponse 2 length: {3}\n"
"\tRequest difference: {4}\n"
"\tResponse difference: {5}\n"
"\tPercent difference: {6}%\n"
"\tDifference direction: {7}"
"\tConfig percent: {8}\n").format(
data["req1_len"], data["resp1_len"], data["req2_len"],
data["resp2_len"], data["req_diff"], data["resp_diff"],
data["percent_diff"], data["dir"], CONF.test.length_diff_percent)
slug = "LENGTH_DIFF_{dir}".format(dir=data["dir"])
return syntribos.signal.SynSignal(
text=text, slug=slug, strength=1.0, data=data, check_name=check_name)
def max_body_length(test):
"""Checks if the response body length is more than max size in the config.
Checks the response body to see if the length is more than the given length
in the config. If it is, returns a Signal.
:returns: SynSignal or None
"""
check_name = "MAX_LENGTH"
if test.init_signals.ran_check(check_name):
resp = test.init_resp
else:
resp = test.test_resp
data = {
"req": resp.request,
"resp": resp,
"req_len": len(resp.request.body or ""),
"resp_len": len(resp.content or ""),
}
text = ("Length:\n"
"\tRequest length: {0}\n"
"\tResponse length: {1}\n".format(data["req_len"],
data["resp_len"]))
slug = "OVER_MAX_LENGTH"
if data["resp_len"] > CONF.test.max_length:
return syntribos.signal.SynSignal(
text=text,
slug=slug,
strength=1.0,
data=data,
check_name=check_name)