Skip to content

Instantly share code, notes, and snippets.

@Nimamoh
Last active August 31, 2022 06:34
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nimamoh/e2df2ba0a99ef221d8cca360c931e5e6 to your computer and use it in GitHub Desktop.
Save Nimamoh/e2df2ba0a99ef221d8cca360c931e5e6 to your computer and use it in GitHub Desktop.
win-gpg-agent-relay
#!/usr/bin/env bash
GNUPGHOME="$HOME/.gnupg"
PIDFILE="$GNUPGHOME/win-gpg-agent-relay.pid"
LOGFILE="$GNUPGHOME/win-gpg-agent-relay.log"
is_pid_running() {
if [[ -z "$1" ]]; then
return 1
fi
ps -p "$1" >/dev/null
return $?
}
# Log only if verbose mode is active
log() {
if [[ -n "$VERBOSE" ]]; then
# shellcheck disable=SC2068
echo >&2 "$@"
fi
}
# Log
info() {
# shellcheck disable=SC2068
echo >&2 "$@"
}
_cleanup() {
info "Cleaning up relay to $GNUPGHOME/S.gpg-agent..."
if is_pid_running "$SOCAT_GPG_AGENT_PID"; then
kill -SIGTERM "$SOCAT_GPG_AGENT_PID" || info "Failed."
fi
info "Cleaning up relay to $GNUPGHOME/S.gpg-agent.ssh..."
if is_pid_running "$SOCAT_GPG_AGENT_SSH_PID"; then
kill -SIGTERM "$SOCAT_GPG_AGENT_SSH_PID" || info "Failed."
fi
}
die() {
if [[ -n "$1" ]]; then
info "$1"
fi
info "Exiting."
exit 1
}
usage() {
info "Usage: win-gpg-agent-relay [OPTIONS] COMMAND"
info ""
info " SUMMARY: Relay local GPG sockets to win-gpg-agent's ones in order to integrate WSL2 and host."
info ""
info " OPTIONS:"
info " -h|--help this page"
info ""
info " -v|--verbose verbose mode"
info ""
info " --wingpgagent-sockets-windir DIR Directory where win-gpg-agent store its sockets."
info " This is a the directory from windows host. ex: 'C:\win-gpg-agent-sockets'"
info ""
info " --wingpgagent-dir DIR Directory where win-gpg-agent is."
info ""
info " COMMAND: start, stop foreground"
}
fg_opts() {
FG_OPTS=()
# Generate opts for passing it to foreground version
if [[ -n "$VERBOSE" ]]; then
FG_OPTS+=("-v")
fi
if [[ -n "$WINGPGAGENT_SOCKETS_WINDIR" ]]; then
# shellcheck disable=SC2089
FG_OPTS+=("--wingpgagent-sockets-windir")
FG_OPTS+=("$WINGPGAGENT_SOCKETS_WINDIR")
fi
if [[ -n "$WINGPGAGENT_DIR" ]]; then
FG_OPTS+=("--wingpgagent-dir")
FG_OPTS+=("$WINGPGAGENT_DIR")
fi
}
main() {
POSITIONAL=()
VERBOSE=""
while (($# > 0)); do
case "$1" in
-v | --verbose)
VERBOSE="ENABLED"
shift # shift once since flags have no values
;;
-h | --help)
usage
exit 0
;;
--wingpgagent-sockets-windir)
numOfArgs=1
if (($# < numOfArgs + 1)); then
shift $#
else
WINGPGAGENT_SOCKETS_WINDIR="$2"
shift $((numOfArgs + 1))
fi
;;
--wingpgagent-dir)
numOfArgs=1
if (($# < numOfArgs + 1)); then
shift $#
else
WINGPGAGENT_DIR="$2"
shift $((numOfArgs + 1))
fi
;;
*) # unknown flag/switch
POSITIONAL+=("$1")
shift
if [[ "${#POSITIONAL[@]}" -gt 1 ]]; then
usage
die
fi
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional params
case "${POSITIONAL[0]}" in
start)
fg_opts
true >"$LOGFILE"
# shellcheck disable=SC2086,SC2090
start-stop-daemon \
--start --oknodo \
--pidfile "$PIDFILE" -m \
--output "$LOGFILE" \
--background \
--name bash --startas "$0" ${VERBOSE:+--verbose} -- foreground "${FG_OPTS[@]}"
;;
stop)
start-stop-daemon --pidfile "$PIDFILE" --stop --remove-pidfile ${VERBOSE:+--verbose}
;;
status)
start-stop-daemon --pidfile "$PIDFILE" --status ${VERBOSE:+--verbose}
local result=$?
case $result in
0) info "$0 is running" ;;
1 | 3) info "$0 is not running" ;;
4) info "$0 unable to determine status" ;;
esac
return $result
;;
foreground)
relay
;;
*)
usage
die
;;
esac
}
mult_by_two_and_max() {
# outputs max(x * 2, y)
# where x is first argument, y the second one
local max
max=${2:-600}
last=${1:-1}
curr=$((last * 2))
curr=$((curr > max ? max : curr))
echo "$curr"
}
sorelay() {
# Serve socket at path $1 relaying to windows AF_LINUX socket $2 through sorelay tool
# return 0 on successfully setup socat, outputs the PID
info "Set up $1 as socket relaying to $2"
local pid
local exec
exec="\'$SORELAY_BIN\' \'$2\'"
socat UNIX-LISTEN:"\"$1\"",fork EXEC:"\"$exec\"",nofork 1>/dev/null 2>&1 &
pid="$!"
# quickly check if socat still running to catch early errors
if ! is_pid_running "$pid"; then
info "socat $1 failed"
return 1
fi
echo "$pid"
}
relay() {
trap _cleanup EXIT
log "Verbose mode: ON"
log "Using win-gpg-agent: $WINGPGAGENT_DIR"
log "Using win-gpg-agent sockets in: $WINGPGAGENT_SOCKETS_WINDIR"
[[ -z "$WINGPGAGENT_SOCKETS_WINDIR" ]] && usage && die "Please provide directory of win-gpg-agent sockets"
[[ -z "$WINGPGAGENT_DIR" ]] && usage && die "Please provide directory of win-gpg-agent"
TMPFOLDER=$(mktemp -d)
{ [[ -z "$TMPFOLDER" ]] && die "Failed creating a temp folder"; } || log "Temp folder: $TMPFOLDER"
cp "$WINGPGAGENT_DIR/sorelay.exe" "$TMPFOLDER/sorelay.exe" || die "Failed to copy sorelay."
SORELAY_BIN="$TMPFOLDER/sorelay.exe"
GPG_AGENT_SOCK="$WINGPGAGENT_SOCKETS_WINDIR/S.gpg-agent"
GPG_AGENT_SSH_SOCK="$WINGPGAGENT_SOCKETS_WINDIR/S.gpg-agent.ssh"
info "Killing previously setup gpg agent..."
echo "KILLAGENT" | gpg-connect-agent >/dev/null 2>&1
if ! SOCAT_GPG_AGENT_PID=$(sorelay "$HOME/.gnupg/S.gpg-agent" "$GPG_AGENT_SOCK"); then die; fi
info "socat running with PID: $SOCAT_GPG_AGENT_PID"
if ! SOCAT_GPG_AGENT_SSH_PID=$(sorelay "$HOME/.gnupg/S.gpg-agent.ssh" "$GPG_AGENT_SSH_SOCK"); then die; fi
info "socat running with PID: $SOCAT_GPG_AGENT_SSH_PID"
while true; do
log -n "Polling GPG agent... "
gpg-connect-agent /bye >/dev/null 2>&1 || die "Failure communicating with S.gpg-agent."
log "OK"
log -n "Polling SSH agent..."
ssh-add -L >/dev/null 2>&1 || die "Failure communicating with S.gpg-agent.ssh."
log "OK"
local time_s
time_s=$(mult_by_two_and_max "${time_s:-5}" 600)
log "Wait $time_s seconds"
sleep "$time_s"
done
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment