aboutsummaryrefslogtreecommitdiff
path: root/audit.bash
blob: 3c424f34d7cd1e6a7a615991889ef82d336c8b74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env bash

pwned_hibp () {
  local sha=$(echo "$1" | tr -d '\n' | shasum | cut -c 1-40 | tr '[:lower:]' '[:upper:]')
  local prefix=$(echo "$sha" | cut -c 1-5)
  local suffix=$(echo "$sha" | cut -c 6-40)
  if [[ $(curl --silent "https://api.pwnedpasswords.com/range/$prefix" | grep "$suffix") ]]; then
    return 1
  fi
  return 0
}

pwned_wordlist () {
  local wordlist="$1"
  local password="$2"
  if [[ ! -f "$wordlist" ]]; then
    die "Wordlist not found"
  fi
  if [[ $(echo "$password" | grep --file="$wordlist") ]]; then
    return 1
  fi
  return 0
}

cmd_audit_password () {
  local opts wordlist use_wordlist=0 use_hibp=0
  opts="$($GETOPT -o w:p -l wordlist:,hibp -n "$PROGRAM" -- "$@")"
  local err=$?
  eval set -- "$opts"
  while true; do case $1 in
    -w|--wordlist) use_wordlist=1; wordlist="${2:-1}"; shift 2 ;;
    -h|--hibp) use_hibp=1; shift ;;
    --) shift; break ;;
  esac done

  local path="${1%/}"
  local passfile="$PREFIX/$path.gpg"
  check_sneaky_paths "$path"
  [[ -f $passfile ]] || die "Passfile not found"

  [[ $use_wordlist -eq 1 ]] || [[ $use_hibp -eq 1 ]] || die "Please use either --hibp or --wordlist"

  local password=$($GPG -d "${GPG_OPTS[@]}" "$passfile" | head -n 1 | tr -d '\n')

  local pwned=0

  if [[ $use_hibp -eq 1 ]]; then
    pwned_hibp "$password"
    if [[ $? -eq 1 ]]; then
      pwned=1
    fi
  fi

  if [[ $use_wordlist -eq 1 ]]; then
    pwned_wordlist "$wordlist" "$password"
    if [[ $? -eq 1 ]]; then
      pwned=1
    fi
  fi

  if [[ $pwned -eq 1 ]]; then
    echo "$path"
    return 1
  fi
  return 0
}


cmd_audit_all_passwords () {
  local prefix_len=$(echo "$PREFIX" | wc -c | tr -d ' ')
  local pwned=0
  for p in $(find "$PREFIX" -name "*.gpg"); do
    path=$(echo "$p" | cut -c "$prefix_len-" | cut -c 2- | sed 's/.gpg$//')
    cmd_audit_password "$@" "$path"
    if [[ $? -ne 0 ]]; then
      pwned=1
    fi
  done
  return $pwned
}

cmd_audit_usage () {
  cat <<-_EOF
Usage:

    $PROGRAM audit [ check ] [ --hibp ] [ --wordlist=list-file ] pass-name
        Check whether a password has been pwned, either by consulting Have I
        Been Pwned or a wordlist file (or both).  You can specify either or
        both options, but without at least one, nothing will happen.

    $PROGRAM audit all [ --hibp ] [ --wordlist=list-file ]
        Check all the passwords in your store against Have I Been Pwned and/or
        the provided wordlist.

More information is available from the pass-audit(1) man page.
_EOF
  exit 0
}

cmd_audit_version () {
  echo "pass-audit v0.1.0"
  exit 0
}

case "$1" in
  version)        shift; cmd_audit_version "$@" ;;
  help|--help|-h) shift; cmd_audit_usage "$@" ;;
  all)            shift; cmd_audit_all_passwords "$@" ;;
  check)          shift; cmd_audit_password "$@" ;;
  *)                     cmd_audit_password "$@" ;;
esac

exit $?

# vim: :set shiftwidth=2 expandtab: