#!/bin/bash
die() { echo "$*" 1>&2; exit 1; }
note() { [ $verbose = yes ] && echo "$*" 1>&2; }
usage() {
cat <<EOU
Usage: $(basename $0) accept [-v] [-u user] [-d domain] [-k keyname] $(basename $0) accept [-v] [-u user] [-d domain] -h hash $(basename $0) remove [-v] [-u user] [-d domain] $(basename $0) hash [-k keyname] $(basename $0) list [-v] [-u user] [-d domain] EOU
exit 2
}
[ -n "$1" ] || usage
command=$1; shift
user=${USER:-$(logname)}
keyname=
hash=
verbose=no
domain="."
while getopts d:h:k:u:v arg; do
case $arg in
d) domain="$OPTARG";;
h) hash="$OPTARG";;
k) keyname="$OPTARG";;
u) user="$OPTARG";;
v) verbose=yes;;
esac
done
shift $(($OPTIND - 1))
hash_for_key() {
string=${1:-'.*'}
HOME=/no/where /usr/bin/security dump-keychain |
awk -v RE="$string" '
/^ 0x00000001/ {
if (matched = ($2 ~ RE)) { name=$0; sub("^.*<blob>=\"", "", name); sub("\"$", "", name); count++; }}
/^ 0x00000006/ {
if (matched) { hash=$2; sub("<blob>=0x", "", hash); print hash, name; }}
'
HOME=/no/where /usr/bin/security dump-keychain |
awk -v RE="$string" '
/^ 0x01000000/ {
if (matched = ($2 ~ RE)) { name=$0; sub("^.*<blob>=\"", "", name); sub("\"$", "", name); count++; }}
/^ 0x06000000/ {
if (matched) { hash=$2; sub("<blob>=0x", "", hash); print hash, name; }}
'
}
get_hash() {
if [ -n "$hash" ]; then echo "$hash"
else hash_for_key "$keyname" |
(
read hash rest
[ -n "$hash" ] || die "No matching keys found"
[ $verbose = yes ] && note "Using key \"$rest\""
echo $hash
)
fi
}
accept_user() {
local hash="$1"
[ -n "$hash" ] || die "No hash specified"
dscl "$domain" -append "/Users/$user" AuthenticationAuthority ";pubkeyhash;$hash"
}
remove_user() {
set -- $(dscl "$domain" -read "/Users/$user" AuthenticationAuthority)
shift while [ -n "$1" ]; do
case "$1" in
\;pubkeyhash\;*)
dscl "$domain" -delete "/Users/$user" AuthenticationAuthority "$1"
[ $verbose = yes ] && note "Removed $1"
;;
esac
shift
done
}
list_hashes() {
set -- $(dscl "$domain" -read "/Users/$user" AuthenticationAuthority)
shift while [ -n "$1" ]; do
case "$1" in
\;pubkeyhash\;*)
echo $1 | sed -e 's/;pubkeyhash;//'
;;
esac
shift
done
}
case "$command" in
hash) hash_for_key "$keyname";;
accept) accept_user $(get_hash);;
remove) remove_user;;
list) list_hashes;;
*) usage;;
esac