X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/distorted-keys/blobdiff_plain/e787e19c99a9df4f49ac77237c58d43df3829e9f..6da76c071f99163e16f3f59dabed3d2490ec9881:/keyfunc.sh.in diff --git a/keyfunc.sh.in b/keyfunc.sh.in index bad5af1..89deccc 100644 --- a/keyfunc.sh.in +++ b/keyfunc.sh.in @@ -38,6 +38,16 @@ if [ -f $ETC/keys.conf ]; then . $ETC/keys.conf; fi ## Maybe turn on debugging. case "${KEYS_DEBUG+t}" in t) set -x ;; esac +## Fake up caller credentials if not called via userv. +case "${USERV_USER+t}" in + t) ;; + *) USERV_USER=${LOGNAME-${USER-$(id -un)}} USERV_UID=$(id -u) ;; +esac +case "${USERV_GROUP+t}" in + t) ;; + *) USERV_GROUP=$(id -Gn) USERV_GID=$(id -gn) ;; +esac + ###-------------------------------------------------------------------------- ### Cleanup handling. @@ -119,6 +129,17 @@ parse_keylabel () { knub=$KEYS/nub/$kowner/$klabel } +runas () { + user=$1 service=$2; shift 2 + ## If the current (effective) user is not USER then reinvoke via `userv', + ## as the specified service, with the remaining arguments. + + case $(id -un) in + "$user") ;; + *) exec userv "$user" "$service" "$@" ;; + esac +} + ###-------------------------------------------------------------------------- ### Input validation functions. @@ -134,7 +155,7 @@ check () { validp=t case "$thing" in *"$nl"*) validp=nil ;; - *) if ! expr >/dev/null "$thing" : "$ckpat\$"; then validp=nil; fi ;; + *) if ! expr >/dev/null "Q$thing" : "Q$ckpat\$"; then validp=nil; fi ;; esac case $validp in nil) echo >&2 "$quis: bad $ckwhat \`$thing'"; exit 1 ;; @@ -143,10 +164,13 @@ check () { ## Regular expressions for validating input. R_IDENTCHARS="A-Za-z0-9_" -R_WORDCHARS="-$R_IDENTCHARS!%@+=" +R_GOODPUNCT="!%@+=" +R_WORDCHARS="-$R_IDENTCHARS$R_GOODPUNCT" R_IDENT="[$R_IDENTCHARS][$R_IDENTCHARS]*" R_WORD="[$R_WORDCHARS][$R_WORDCHARS]*" +R_ACLCHARS="][$R_IDENTCHARS$R_GOODPUNCT*?:.#" R_WORDSEQ="[$R_WORDCHARS[:space:]][$R_WORDCHARS[:space:]]*" +R_ACL="[$R_ACLCHARS[:space:]-][$R_ACLCHARS[:space:]-]*" R_NUMERIC='\(\([1-9][0-9]*\)\{0,1\}0\{0,1\}\)' R_LABEL="\($R_WORD\(/$R_WORD\)*\)" R_LINE=".*" @@ -216,6 +240,16 @@ EOF done } +dumpprops () { + prefix=$1 + ## Write the properties stored in the variables beginning with PREFIX. + + set | sed -n "/^$prefix/{s/=.*\$//;p}" | sort | while read name; do + eval value=\$$name + echo "${name#$prefix}=$value" + done +} + defprops () { name=$1 ## Define a properties table NAME. @@ -231,6 +265,11 @@ random t $R_WORD nub_hash t $R_WORD nubid_hash t $R_WORD nub_random_bytes t $R_NUMERIC +acl_encrypt t $R_ACL +acl_decrypt t $R_ACL +acl_sign t $R_ACL +acl_verify t $R_ACL +acl_info t $R_ACL EOF readprops () { @@ -279,8 +318,11 @@ nubid () { ## Compute a hash of the key nub in stdin, and write it to stdout in hex. ## The property `nubid_hash' is used. - { echo "distorted-keys nubid"; cat -; } | - openssl dgst -${kprop_nubid_hash-sha256} + ## Stupid dance because the output incompatibly grew a filename, in order + ## to demonstrate the same idiocy as GNU mumblesum. + set _ $({ echo "distorted-keys nubid"; cat -; } | + openssl dgst -${kprop_nubid_hash-sha256}) + echo $2 } subst () { @@ -329,9 +371,10 @@ subst () { } read_profile () { - profile=$1 + owner=$1 profile=$2 ## Read property settings from a profile. The PROFILE name has the form - ## [USER:]LABEL. Properties are set using `setprops' with prefix `kprop_'. + ## [USER:]LABEL; USER defaults to OWNER. Properties are set using + ## `setprops' with prefix `kprop_'. reqtmp case "$profile" in @@ -339,7 +382,7 @@ read_profile () { label=${profile#:} uservp=nil ;; *) - user=$USERV_USER label=$profile uservp=t + user=$kowner label=$profile uservp=t ;; *:*) user=${profile%%:*} label=${profile#*:} uservp=t @@ -352,7 +395,7 @@ read_profile () { case $uservp in t) checkword "profile user" "$user" - userv "$user" cryptop-profile "$label" >$tmp/profile + userv "$user" cryptop-profile "$label" >$tmp/profile $tmp/profile @@ -426,16 +469,18 @@ k_verify () { notsupp verify; } prepare () { key=$1 op=$2 ## Prepare for a crypto operation OP, using the KEY. This validates the - ## key label, reads the profile, and checks the access-control list. + ## key label, reads the profile, and checks the access-control list. If OP + ## is `-' then allow the operation unconditionally. ## Find the key properties. parse_keylabel "$key" if [ ! -d $kdir ]; then echo >&2 "$quis: unknown key \`$key'"; exit 1; fi readmeta $kdir - read_profile "$profile" + read_profile $kowner "$profile" ## Check whether we're allowed to do this thing. This is annoyingly ## fiddly. + case $op in -) return ;; esac eval acl=\${kprop_acl_$op-!owner} verdict=forbid while :; do @@ -522,6 +567,31 @@ c_sysverify () { c_sysop verify "$1" /dev/null; } ###-------------------------------------------------------------------------- ### Recovery operations. +sharethresh () { + pf=$1 + ## Return the sharing threshold from the parameter file PARAM. + + read param <"$pf" + case "$param" in + shamir-params:*) ;; + *) + echo >&2 "$quis: secret sharing parameter file damaged (wrong header)" + exit 1 + ;; + esac + t=";${param#*:}" + case "$t" in + *";t="*) ;; + *) + echo >&2 "$quis: secret sharing parameter file damaged (missing t)" + exit 1 + ;; + esac + t=${t#*;t=} + t=${t%%;*} + echo "$t" +} + stash () { recov=$1 label=$2 ## Stash a copy of stdin encrypted under the recovery key RECOV, with a