Skip to content

Commit fab42dd

Browse files
committed
Backport HTTP 'Age' header field
See #2032 / #2067, kudos @Wahnes. This is a backport for 3.0 Currently, when "HTTP clock skew" is calculated, this is taken to be the difference between the timestamp of the moment the HTTPS request was sent and the date given in the HTTP Date header. This does not yield valid results in case a HTTP cache is used, either on the client side or on the server side. According to the HTTP specs, the Date field will contain the timestamp the response was created, which may not be the timestamp the response was delivered. Consider the following example that queries the Varnish project's web server. Note that Varnish is a popular HTTP caching server, so HTTP caching will of course be used when serving HTTP responses from this project's web server. testssl.sh https://varnish-cache.org/ This will typically output a HTTP clock skew of some thousand seconds. The patch takes into account the HTTP Age header that caching servers add to the HTTP response to signal the response's freshness. As client-side caches normally do not cache HTTPS requests (except maybe for "enterprise" HTTP proxy caches that do MITM HTTPS proxying), this is mostly targeted to HTTPS websites that employ server side HTTP caching. Addtional polishing: * address my comments in #2032 * add JSON field HTTP_headerAge if they exists * output HTTP_AGE if it was detected * do stripping of line feeds closer to where variables were set
1 parent 2cd0ab5 commit fab42dd

1 file changed

Lines changed: 15 additions & 3 deletions

File tree

testssl.sh

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ TLS_NOW="" # Similar
401401
TLS_DIFFTIME_SET=false # Tells TLS functions to measure the TLS difftime or not
402402
NOW_TIME=""
403403
HTTP_TIME=""
404+
HTTP_AGE="" # Age Header, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Age + RFC 7234
404405
GET_REQ11=""
405406
START_TIME=0 # time in epoch when the action started
406407
END_TIME=0 # .. ended
@@ -2160,13 +2161,15 @@ run_http_header() {
21602161
printf "$GET_REQ11" | $OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI") >$HEADERFILE 2>$ERRFILE
21612162
NOW_TIME=$(date "+%s")
21622163
HTTP_TIME=$(awk -F': ' '/^date:/ { print $2 } /^Date:/ { print $2 }' $HEADERFILE)
2164+
HTTP_AGE=$(awk -F': ' '/^[aA][gG][eE]: / { print $2 }' $HEADERFILE)
21632165
HAD_SLEPT=0
21642166
else
21652167
# 1st GET request hung and needed to be killed. Check whether it succeeded anyway:
21662168
if grep -Eiaq "XML|HTML|DOCTYPE|HTTP|Connection" $HEADERFILE; then
21672169
# correct by seconds we slept, HAD_SLEPT comes from wait_kill()
21682170
NOW_TIME=$(($(date "+%s") - HAD_SLEPT))
21692171
HTTP_TIME=$(awk -F': ' '/^date:/ { print $2 } /^Date:/ { print $2 }' $HEADERFILE)
2172+
HTTP_AGE=$(awk -F': ' '/^[aA][gG][eE]: / { print $2 }' $HEADERFILE)
21702173
else
21712174
prln_warning " likely HTTP header requests failed (#lines: $(wc -l $HEADERFILE | awk '{ print $1 }'))"
21722175
[[ "$DEBUG" -lt 1 ]] && outln "Rerun with DEBUG>=1 and inspect $HEADERFILE\n"
@@ -2198,7 +2201,9 @@ run_http_header() {
21982201
fi
21992202

22002203
# Populate vars for HTTP time
2201-
debugme echo "NOW_TIME: $NOW_TIME | HTTP_TIME: $HTTP_TIME"
2204+
[[ -n "$HTTP_AGE" ]] && HTTP_AGE="$(strip_lf "$HTTP_AGE")"
2205+
[[ -n "$HTTP_TIME" ]] && HTTP_TIME="$(strip_lf "$HTTP_TIME")"
2206+
debugme echo "NOW_TIME: $NOW_TIME | HTTP_AGE: $HTTP_AGE | HTTP_TIME: $HTTP_TIME"
22022207

22032208
# Quit on first empty line to catch 98% of the cases. Next pattern is there because the SEDs tested
22042209
# so far seem not to be fine with header containing x0d x0a (CRLF) which is the usual case.
@@ -2324,19 +2329,26 @@ run_http_date() {
23242329
out "${spaces}local: $(LC_ALL=C TZ=GMT date "+%a, %d %b %Y %T %Z")"
23252330
fileout "$jsonID" "INFO" "$HTTP_TIME - $(TZ=GMT date "+%a, %d %b %Y %T %Z")"
23262331
else
2332+
# modifying the global from string to a number
23272333
HTTP_TIME="$(parse_date "$HTTP_TIME" "+%s" "%a, %d %b %Y %T %Z" 2>>$ERRFILE)"
2328-
difftime=$((HTTP_TIME - NOW_TIME))
2334+
difftime=$((HTTP_TIME + HTTP_AGE - NOW_TIME))
23292335
[[ $difftime != "-"* ]] && [[ $difftime != "0" ]] && difftime="+$difftime"
23302336
# process was killed, so we need to add an error
23312337
[[ $HAD_SLEPT -ne 0 ]] && difftime="$difftime (± 1.5)"
23322338
out "$difftime sec from localtime";
23332339
fileout "$jsonID" "INFO" "$difftime seconds from localtime"
23342340
fi
2341+
if [[ -n "$HTTP_AGE" ]]; then
2342+
outln
2343+
pr_bold " HTTP Age, RFC 7234 "
2344+
out "$HTTP_AGE"
2345+
fileout "HTTP_headerAge" "INFO" "$HTTP_AGE seconds"
2346+
fi
23352347
else
23362348
out "Got no HTTP time, maybe try different URL?";
23372349
fileout "$jsonID" "INFO" "Got no HTTP time, maybe try different URL?"
23382350
fi
2339-
debugme tm_out ", HTTP_TIME in epoch: $HTTP_TIME"
2351+
debugme tm_out ", HTTP_TIME + HTTP_AGE in epoch: $HTTP_TIME / $HTTP_AGE"
23402352
outln
23412353
match_ipv4_httpheader "$1"
23422354
return 0

0 commit comments

Comments
 (0)