#!/bin/bash # Copyright (c) 2013 Peter Palfrader # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. set -e set -u usage() { echo "Usage: $0 [] [" echo "Options:" echo " -a use this authority [$AUTH]" echo " -l log dir [$LOGDIR]" echo " -m send mail when a certificate mismatch is found" echo " -v be a bit verbose" echo " -h print this help" } AUTH=tor.noreply.org PER_RUN=60 DATADIR=$(mktemp -d "/tmp/tor-checks-XXXXXX") DUMPFILE=$(tempfile) DEFAULT_CHECKHOSTS="www.torproject.org" LOGDIR="tor-exit-ssl-check-many.log" CACHEDIR="tor-exit-ssl-check-many.cache" MAIL=0 trap "rm -rf '$DATADIR' '$DUMPFILE'" EXIT mkdir -vp "$LOGDIR" mkdir -vp "$CACHEDIR" LOG="$LOGDIR/log" CTR=0 HOSTNAME=$(hostname) VERBOSE=0 while getopts "vha:l:m" OPTION do case "$OPTION" in v) VERBOSE=$((VERBOSE + 1)) ;; h) usage exit 0 ;; a) AUTH="$OPTARG" ;; l) LOGDIR="$OPTARG" ;; m) MAIL=1 ;; *) usage >&2 exit 1 esac done shift $(($OPTIND - 1)) if [ "${1:-}" = "--help" ]; then usage exit 0 elif [ "$#" != 0 ]; then usage >&2 exit 1 fi declare -a CHECKHOSTS=("$@") if [ "${#CHECKHOSTS[@]}" = 0 ]; then for i in $DEFAULT_CHECKHOSTS; do CHECKHOSTS[${#CHECKHOSTS[@]}]="$i" done fi run_some_checks() { local idx=$(( RANDOM % ${#CHECKHOSTS[@]} )) local host="${CHECKHOSTS[$idx]}" wget -q -O - "http://$AUTH"/tor/status-vote/current/consensus | \ grep -v BadExit | grep '^s .*Exit' -B1 |\ awk '$1 == "r" {print $3}' |\ sort -R | \ head -n "$PER_RUN" | \ while read fpr; do [ "$VERBOSE" = 0 ] || echo -n "Checking $host at $fpr..." if tor-exit-ssl-check -c "$CACHEDIR" -d "$DATADIR" "$fpr" $host > "$DUMPFILE" 2>&1; then ecode=0 else ecode="$?" fi [ "$VERBOSE" = 0 ] || echo "$ecode" prefix="[$(TZ=UTC date +%Y-%m-%dT%H:%M:%SZ)][$fpr][EC=$ecode]" case "$ecode" in 0) echo "$prefix OK" >> "$LOG";; 2) echo "$prefix connect failed" >> "$LOG";; 4) echo "$prefix handshake failed" >> "$LOG";; 8) lf="$LOGDIR/$(date +%s).$HOSTNAME.$$.$CTR" echo "$prefix differences - logged as $lf" >> "$LOG" CTR=$((CTR + 1)) echo "$fpr" > "$lf" echo >> "$lf" cat "$DUMPFILE" >> "$lf" echo >> "$lf" wget -q -O - http://"$AUTH"/tor/server/fp/$(echo "$fpr" | perl -MMIME::Base64 -e "print unpack(\"H*\", decode_base64(<>)),\"\n\"") >> "$lf" if [ "$MAIL" -gt 0 ]; then (echo "Log file at $lf:"; echo; cat "$lf") | mail -s "certificate mismatch found for relay $fpr" "$USER" fi ;; *) echo "$prefix unknown exit code" >> "$LOG" echo "$prefix unknown exit code" >&2 cp $DUMPFILE "$LOGDIR/failed-output" exit 1 esac done } while : ; do run_some_checks sleep 15 done