mirror of
https://github.com/ben-grande/qusal.git
synced 2024-10-01 02:35:49 -04:00
refactor: git Qrexec helper with drop-in commands
Drop-in scripts can complement the remote-helper ability. Basic trace of the communication of git with the helper.
This commit is contained in:
parent
a27493c5d9
commit
a820751ba3
@ -6,6 +6,10 @@
|
||||
|
||||
set -eu
|
||||
|
||||
case "${GIT_TRACE_HELPER:-}" in
|
||||
true|1) set -x;;
|
||||
esac
|
||||
|
||||
usage(){
|
||||
echo "Usage: ${helper} [<qube>] [<repository>]"
|
||||
echo "Note: qube defaults to '@default' and repository to the current repository"
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
## Portable git-remote-helper.
|
||||
## Rename this helper to git-remote-<scheme>.
|
||||
## Valid URL format: <scheme>://<authority>/<path>.
|
||||
## Supported commands: capabilities, connect.
|
||||
## URL: <scheme>://<authority>/<path>[?query=value][&another_query=value]
|
||||
## Capabilities commands are sent to git-remote-<scheme>-<capability>.
|
||||
|
||||
set -eu
|
||||
|
||||
usage(){
|
||||
echo "Usage: ${helper} <remote> [${scheme}://<authority>/<path>]" >&2
|
||||
echo "Usage: ${helper} <remote> [${scheme}://<authority>/<path>[?query=value][&other_query=value]]" >&2
|
||||
}
|
||||
|
||||
die(){
|
||||
@ -21,6 +21,12 @@ die(){
|
||||
exit 1
|
||||
}
|
||||
|
||||
log(){
|
||||
case "${GIT_TRACE_REMOTE_HELPER:-}" in
|
||||
true|1) echo "${@}" >&2
|
||||
esac
|
||||
}
|
||||
|
||||
## Validate URL and return it without the scheme.
|
||||
validate_url(){
|
||||
url_valid=""
|
||||
@ -31,30 +37,79 @@ validate_url(){
|
||||
## Checks if Authority and Path exist, but not if they are valid, this is
|
||||
## implementation specific and should be checked by the connect helper.
|
||||
case "${url_check}" in
|
||||
"${scheme}"://*?/*?) url_valid="$(echo "${url_check}" | sed "s|.*://||")";;
|
||||
"${scheme}"://*?/*?) url_valid="${url_check}";;
|
||||
"${scheme}"://*?) die "URL has no path to resource: '${url_check}'";;
|
||||
"${scheme}"://) die "URL has no authority: '${url_check}'";;
|
||||
*?://*) die "URL has unsupported scheme: '${scheme_user_url}'";;
|
||||
*) die "URL has no scheme: '${url_check}'";;
|
||||
esac
|
||||
|
||||
urn_pattern="[0-9A-Za-z@:_.-]+/[0-9A-Za-z_.-]+(\?[0-9A-Za-z=&_-]*)?"
|
||||
if ! (echo "${url_valid}" | grep -qE "^${scheme}://${urn_pattern}$")
|
||||
then
|
||||
die "URL contains forbidden characters"
|
||||
fi
|
||||
|
||||
echo "${url_valid}"
|
||||
}
|
||||
|
||||
get_urn(){
|
||||
echo "${1#*://}"
|
||||
}
|
||||
|
||||
get_authority(){
|
||||
echo "${1%%/*}"
|
||||
}
|
||||
|
||||
get_path(){
|
||||
echo "${1##*/}" | cut -d "?" -f1
|
||||
}
|
||||
|
||||
get_query(){
|
||||
query=""
|
||||
## If URL contains '?', set query.
|
||||
if test "${1}" != "${1##*\?}"; then
|
||||
query="${1##*\?}"
|
||||
fi
|
||||
echo "${query}"
|
||||
}
|
||||
|
||||
## Find remote-<scheme>-<command>.
|
||||
find_capabilities(){
|
||||
cap_helpers=""
|
||||
for f in "${exec_path}/${script}"-*; do
|
||||
test -f "${f}" || continue
|
||||
test -x "${f}" || continue
|
||||
if test -z "${cap_helpers}"; then
|
||||
cap_helpers="${f##*"${script}-"}"
|
||||
else
|
||||
cap_helpers="${cap_helpers}\n${f##*"${script}-"}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${cap_helpers}"
|
||||
}
|
||||
|
||||
## Send capabilities to remote helper specific for that capability.
|
||||
send_cap(){
|
||||
exec_path="$(git --exec-path)"
|
||||
test -n "${exec_path}" || die "Couldn't locate Git's executables path"
|
||||
|
||||
cap="${1}"
|
||||
shift
|
||||
cap_file="${script}-${cap}"
|
||||
cap_path="${exec_path}/${cap_file}"
|
||||
|
||||
test -e "${cap_path}" || die "Git's exec path missing: '${cap_file}'"
|
||||
test -x "${cap_path}" || die "Git script is not executable: '${cap_file}'"
|
||||
if ! (echo "${capabilities}" | grep -q "^${cap}$"); then
|
||||
die "Unsupported capability: '${cap}'"
|
||||
fi
|
||||
|
||||
"${cap_path}" "${@}"
|
||||
cap_helper="${helper}-${cap}"
|
||||
#cap_file="${script}-${cap}"
|
||||
#cap_path="${exec_path}/${cap_file}"
|
||||
|
||||
## Call capability helper.
|
||||
remote="${remote}" pushurl="${pushurl}" url="${url}" \
|
||||
authority="${authority}" path="${path}" query="${query}" \
|
||||
pushauthority="${pushauthority}" pushpath="${pushpath}" \
|
||||
pushquery="${pushquery}" \
|
||||
git "${cap_helper}" "${@}"
|
||||
#"${cap_path}" "${@}"
|
||||
}
|
||||
|
||||
## Basic requirements.
|
||||
@ -75,7 +130,10 @@ esac
|
||||
## Get URL and Push URL (fallback to URL)
|
||||
case "${2-}" in
|
||||
"")
|
||||
## Happens when 'remote-qrexec' is called directly from the command-line.
|
||||
## Necessary when the remote-helper is called from the command-line.
|
||||
if ! git remote get-url "${remote}" >/dev/null 2>&1; then
|
||||
die "Remote doesn't exist: '${remote}'"
|
||||
fi
|
||||
url="$(git remote get-url "${remote}" || true)"
|
||||
pushurl="$(git remote get-url --push "${remote}" || true)"
|
||||
;;
|
||||
@ -85,23 +143,32 @@ esac
|
||||
test -n "${url}" || die "Remote URL is unset"
|
||||
test -n "${pushurl}" || die "Remote Push URL is unset"
|
||||
|
||||
url="$(validate_url "${url}")"
|
||||
pushurl="$(validate_url "${pushurl}")"
|
||||
pushurn="$(get_urn "${pushurl}")"
|
||||
pushauthority="$(get_authority "${pushurn}")"
|
||||
pushpath="$(get_path "${pushurn}")"
|
||||
pushquery="$(get_query "${pushurn}")"
|
||||
|
||||
url="$(validate_url "${url}")"
|
||||
urn="$(get_urn "${url}")"
|
||||
authority="$(get_authority "${urn}")"
|
||||
path="$(get_path "${urn}")"
|
||||
query="$(get_query "${urn}")"
|
||||
|
||||
exec_path="$(git --exec-path)"
|
||||
test -n "${exec_path}" || die "Git's executables path not found"
|
||||
|
||||
capabilities="$(find_capabilities)"
|
||||
|
||||
## Communicate with the git-remote-helpers protocol.
|
||||
while read -r cmd arg; do
|
||||
log "<- $cmd $arg"
|
||||
case "${cmd}" in
|
||||
"") exit 0;;
|
||||
"capabilities") printf "connect\n\n";;
|
||||
"connect")
|
||||
printf "\n";
|
||||
case "${arg}" in
|
||||
git-upload-pack) send_cap "${cmd}" "${arg}" "${url}";;
|
||||
git-receive-pack) send_cap "${cmd}" "${arg}" "${pushurl}";;
|
||||
"") die "Argument can't be empty";;
|
||||
*) die "Unsupported argument: '${arg}'";;
|
||||
esac
|
||||
;;
|
||||
*) die "Unsupported command: '${cmd}'";;
|
||||
capabilities)
|
||||
for c in ${capabilities}; do log "-> ${c}"; done; log "->"
|
||||
printf %s"${capabilities}\n\n";;
|
||||
*) send_cap "${cmd}" "${arg}";;
|
||||
esac
|
||||
done
|
||||
|
||||
log "<-"
|
||||
|
@ -4,11 +4,10 @@
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
## Should be called by git-remote-qrexec.
|
||||
set -eu
|
||||
|
||||
usage(){
|
||||
echo "Usage: ${helper} git-upload-pack|git-receive-pack <qube>/<path>"
|
||||
echo "Usage: ${helper} (git-upload-pack|git-receive-pack)"
|
||||
echo "Note: ${helper} is supposed to be called by ${parent_helper}"
|
||||
exit 1
|
||||
}
|
||||
@ -18,45 +17,69 @@ die(){
|
||||
exit 1
|
||||
}
|
||||
|
||||
log(){
|
||||
case "${GIT_TRACE_REMOTE_HELPER:-}" in
|
||||
true|1) echo "${@}" >&2
|
||||
esac
|
||||
}
|
||||
|
||||
## Establish capability working.
|
||||
log "->"
|
||||
printf "\n"
|
||||
|
||||
helper="${0##*/git-}"
|
||||
parent_helper="${helper%-*}"
|
||||
scheme="${helper##*remote-}"; scheme="${scheme%%-*}"
|
||||
|
||||
case "${1-}" in
|
||||
-h|--?help|"") usage;;
|
||||
*) arg="${1}";;
|
||||
esac
|
||||
case "${2-}" in
|
||||
"") usage;;
|
||||
*) url="${2}";;
|
||||
esac
|
||||
|
||||
test -n "${remote-}" || die "Remote is unset"
|
||||
test -n "${url-}" || die "URL is unset"
|
||||
test -n "${authority-}" || die "URL Authority is unset"
|
||||
test -n "${path-}" || die "URL Path is unset"
|
||||
: "${query-}"
|
||||
test -n "${pushurl-}" || die "PushURL is unset"
|
||||
test -n "${pushauthority-}" || die "PushURL Authority is unset"
|
||||
test -n "${pushpath-}" || die "PushURL Path is unset"
|
||||
: "${pushquery-}"
|
||||
|
||||
case "${arg}" in
|
||||
git-upload-pack) rpc=GitFetch;;
|
||||
git-receive-pack) rpc=GitPush;;
|
||||
"") die "Argument can't be empty";;
|
||||
*) die "Unsupported argument: '${arg}'";;
|
||||
git-receive-pack) rpc=GitPush; url="${pushurl}";
|
||||
authority="${pushauthority}"; path="${pushpath}"; query="${pushquery}";;
|
||||
"") die "${helper} requires an argument";;
|
||||
*) die "${helper} called with unsupported argument: '${arg}'";;
|
||||
esac
|
||||
|
||||
qube="$(echo "${url}" | cut -d "/" -f1)"
|
||||
repo="$(echo "${url}" | cut -d "/" -f2-)"
|
||||
test -n "${repo}" || die "Repository name can't be empty"
|
||||
test -n "${path}" || die "Repository name can't be empty"
|
||||
|
||||
vendor="qusal"
|
||||
default_qube="sys-git"
|
||||
rpc_cmd="${vendor}.${rpc}+${repo}"
|
||||
rpc_cmd="${vendor}.${rpc}+${path}"
|
||||
|
||||
if echo "${query}" | grep -qE "(^|&)verify_signatures=(1|[tT]rue|yes|on)($|&)"
|
||||
then
|
||||
die "Remote helper does not support signature verification yet"
|
||||
fi
|
||||
|
||||
if command -v qrexec-client-vm >/dev/null; then
|
||||
exec qrexec-client-vm -- "${qube}" "${rpc_cmd}"
|
||||
log "->" qrexec-client-vm -- "${authority}" "${rpc_cmd}"
|
||||
exec qrexec-client-vm -- "${authority}" "${rpc_cmd}"
|
||||
elif command -v qrexec-client >/dev/null; then
|
||||
qubes_version="$(awk -F '=' '/^VERSION_ID=/{print $2}' /etc/os-release)"
|
||||
if test "$(echo "${qubes_version}" | tr -d ".")" -le 41; then
|
||||
if test "${qube}" = "@default"; then
|
||||
qube="${default_qube}"
|
||||
if test "${authority}" = "@default"; then
|
||||
authority="${default_qube}"
|
||||
fi
|
||||
else
|
||||
policy="$(qrexec-policy --assume-yes-for-ask dom0 "${qube}" "${rpc_cmd}")"
|
||||
qube="$(echo "${policy}" | awk -F '=' '/^target=/{print $2}')"
|
||||
policy="$(qrexec-policy --assume-yes-for-ask dom0 "${authority}" "${rpc_cmd}")"
|
||||
authority="$(echo "${policy}" | awk -F '=' '/^target=/{print $2}')"
|
||||
fi
|
||||
exec qrexec-client -d "${qube}" -- "DEFAULT:QUBESRPC ${rpc_cmd} dom0"
|
||||
else
|
||||
log "->" qrexec-client -d "${authority}" -- "DEFAULT:QUBESRPC ${rpc_cmd} dom0"
|
||||
exec qrexec-client -d "${authority}" -- "DEFAULT:QUBESRPC ${rpc_cmd} dom0"
|
||||
fi
|
||||
|
||||
die "Qrexec programs not found: qrexec-client-vm, qrexec-client"
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user