From 1c35165652fae8410eec8c8bb31ef86ddec8ec6a Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 23 Oct 2021 12:36:42 -0400 Subject: move files to src/ --- AnonymousAccessCommand | 126 --------------------------------------------- AuthorizedKeysCommand | 15 ------ Makefile | 9 ++-- anonymous-access.conf | 10 ---- src/AnonymousAccessCommand | 126 +++++++++++++++++++++++++++++++++++++++++++++ src/AuthorizedKeysCommand | 15 ++++++ src/anonymous-access.conf | 10 ++++ src/tests.sh | 66 ++++++++++++++++++++++++ tests.makefile | 2 +- tests.sh | 66 ------------------------ 10 files changed, 224 insertions(+), 221 deletions(-) delete mode 100755 AnonymousAccessCommand delete mode 100755 AuthorizedKeysCommand delete mode 100644 anonymous-access.conf create mode 100755 src/AnonymousAccessCommand create mode 100755 src/AuthorizedKeysCommand create mode 100644 src/anonymous-access.conf create mode 100644 src/tests.sh delete mode 100644 tests.sh diff --git a/AnonymousAccessCommand b/AnonymousAccessCommand deleted file mode 100755 index 443d25e..0000000 --- a/AnonymousAccessCommand +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh -default_msg() -{ - sshfpline="$(get_sshfp_authline ${SSH_CLIENT%% *})" - cat <&2 - - You are: - - $authline - $sshfpline - -EOF -} - -get_sshfp_authline() -{ - ( - r=${1:-.} - key=$(mktemp) || exit - trap 'rm -rf "$key"' EXIT - echo "$authline" > "$key" - get_sshfp "$key" "$r" - ) -} - -get_sshfp() -{ - ( - key="$1" - r="${2:-.}" - dns=$(mktemp) || exit - trap 'rm -rf "$dns"' EXIT - - ssh-keygen -r "$r" -f "$key" > "$dns" - exec < "$dns" - while read line - do - set -- $line - if [ "$3 $5" = "SSHFP 2" ] - then - echo "$line" - break - fi - done - ) -} - -ssh_client_fingerprint_base16() -{ - set -- $(get_sshfp_authline) - [ "$6" ] - echo $6 -} - -check_if_self_forge() -{ - # TODO: don't use description, but something else. - local dir="$1" - [ -d "$dir" ] || exit - [ -r "$dir"/description ] || exit - read description < "$dir"/description - if [ "$description" != self-forge ] && [ "$(GIT_DIR=$dir git config core.self-forge)" != true ] - then - echo 'Error: access denied. The specified directory is not a self-forge.' >&2 - exit - fi -} - -read authtype authline < "$SSH_USER_AUTH" || exit -[ "$authtype" = publickey ] || exit - -cmd=${SSH_ORIGINAL_COMMAND%% *} - -case "$cmd" in - git-send-pack | git-upload-pack) - GIT_NAMESPACE= - ;; - git-receive-pack) - export GIT_NAMESPACE="$(ssh_client_fingerprint_base16)" - [ "$GIT_NAMESPACE" ] || exit - ;; - *) - default_msg - exit - ;; -esac - -arg=${SSH_ORIGINAL_COMMAND#* } -arg=${arg%\'} -arg=${arg#\'} -case "$arg" in - *\'*) exit ;; - *.git) ;; - *) arg=$arg/.git ;; -esac - -dir=$(readlink -e "$arg") || exit - -check_if_self_forge "$dir" - -with_allowCurrentBranch() -{ - local cmd="$1" dir="$2" - ( - set -eC - lockfile=$GIT_DIR/index.lock - echo $$ > "$lockfile" - trap 'rm -f "$lockfile"' EXIT - - # This doesn't seem very secure. Need to patch git probably. - for deny in CurrentBranch # DeleteCurrent - do git config receive.deny$deny false - done - "$@" - for deny in CurrentBranch # DeleteCurrent - do git config receive.deny$deny true - done - ) -} - -if [ "$GIT_NAMESPACE" ] -then - GIT_DIR=$dir with_allowCurrentBranch "$cmd" "$dir" -else - "$cmd" "$dir" -fi diff --git a/AuthorizedKeysCommand b/AuthorizedKeysCommand deleted file mode 100755 index 6e13063..0000000 --- a/AuthorizedKeysCommand +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -username=$1 -userhome=$2 -fingerprint=$3 -authline="$4 $5" - -case "$userhome" in - *'"'*) exit ;; -esac - -usercommand=$userhome/.ssh/AnonymousAccessCommand - -[ -x "$usercommand" ] || exit - -printf 'command="%s",no-port-forwarding %s\n' "$usercommand $fingerprint" "$authline" diff --git a/Makefile b/Makefile index b203340..4983669 100644 --- a/Makefile +++ b/Makefile @@ -18,11 +18,14 @@ USER_SSH_CONFIG_DIR = ~$(USER)/.ssh shared: install git config core.self-forge true +SRC = src +SOURCES = $(addprefix $(SRC), AnonymousAccessCommand anonymous-access.conf AuthorizedKeysCommand) + install: - install -t $(USER_SSH_CONFIG_DIR) AnonymousAccessCommand + install -t $(USER_SSH_CONFIG_DIR) $(SRC)/AnonymousAccessCommand $(ROOT_INSTALL) -d "$(SSH_CONFIG_DIR)" "$(SSHD_CONFIG_DIR)" "$(SSH_LIB_DIR)" || true - $(ROOT_INSTALL) -m0644 -t "$(SSHD_CONFIG_DIR)" anonymous-access.conf || true - $(ROOT_INSTALL) -t "$(SSH_LIB_DIR)" AuthorizedKeysCommand || true + $(ROOT_INSTALL) -m0644 -t "$(SSHD_CONFIG_DIR)" $(SRC)/anonymous-access.conf || true + $(ROOT_INSTALL) -t "$(SSH_LIB_DIR)" $(SRC)/AuthorizedKeysCommand || true [ -e "$(SSH_LIB_DIR)"/AuthorizedKeysCommand ] || $(SUDO) ln -s -t /etc/ssh "$(SSH_LIB_DIR)"/AuthorizedKeysCommand README.html: README.md diff --git a/anonymous-access.conf b/anonymous-access.conf deleted file mode 100644 index 5cd6b6a..0000000 --- a/anonymous-access.conf +++ /dev/null @@ -1,10 +0,0 @@ -ExposeAuthInfo=yes -AuthorizedKeysCommandUser=root -AuthorizedKeysCommand=/etc/ssh/AuthorizedKeysCommand %u %h %f "%t %k" - -# %u The username. -# %h The home directory of the user. -# %f The fingerprint of the key or certificate. -# %t The key or certificate type. -# %k The base64-encoded key or certificate for authentication. - diff --git a/src/AnonymousAccessCommand b/src/AnonymousAccessCommand new file mode 100755 index 0000000..443d25e --- /dev/null +++ b/src/AnonymousAccessCommand @@ -0,0 +1,126 @@ +#!/bin/sh +default_msg() +{ + sshfpline="$(get_sshfp_authline ${SSH_CLIENT%% *})" + cat <&2 + + You are: + + $authline + $sshfpline + +EOF +} + +get_sshfp_authline() +{ + ( + r=${1:-.} + key=$(mktemp) || exit + trap 'rm -rf "$key"' EXIT + echo "$authline" > "$key" + get_sshfp "$key" "$r" + ) +} + +get_sshfp() +{ + ( + key="$1" + r="${2:-.}" + dns=$(mktemp) || exit + trap 'rm -rf "$dns"' EXIT + + ssh-keygen -r "$r" -f "$key" > "$dns" + exec < "$dns" + while read line + do + set -- $line + if [ "$3 $5" = "SSHFP 2" ] + then + echo "$line" + break + fi + done + ) +} + +ssh_client_fingerprint_base16() +{ + set -- $(get_sshfp_authline) + [ "$6" ] + echo $6 +} + +check_if_self_forge() +{ + # TODO: don't use description, but something else. + local dir="$1" + [ -d "$dir" ] || exit + [ -r "$dir"/description ] || exit + read description < "$dir"/description + if [ "$description" != self-forge ] && [ "$(GIT_DIR=$dir git config core.self-forge)" != true ] + then + echo 'Error: access denied. The specified directory is not a self-forge.' >&2 + exit + fi +} + +read authtype authline < "$SSH_USER_AUTH" || exit +[ "$authtype" = publickey ] || exit + +cmd=${SSH_ORIGINAL_COMMAND%% *} + +case "$cmd" in + git-send-pack | git-upload-pack) + GIT_NAMESPACE= + ;; + git-receive-pack) + export GIT_NAMESPACE="$(ssh_client_fingerprint_base16)" + [ "$GIT_NAMESPACE" ] || exit + ;; + *) + default_msg + exit + ;; +esac + +arg=${SSH_ORIGINAL_COMMAND#* } +arg=${arg%\'} +arg=${arg#\'} +case "$arg" in + *\'*) exit ;; + *.git) ;; + *) arg=$arg/.git ;; +esac + +dir=$(readlink -e "$arg") || exit + +check_if_self_forge "$dir" + +with_allowCurrentBranch() +{ + local cmd="$1" dir="$2" + ( + set -eC + lockfile=$GIT_DIR/index.lock + echo $$ > "$lockfile" + trap 'rm -f "$lockfile"' EXIT + + # This doesn't seem very secure. Need to patch git probably. + for deny in CurrentBranch # DeleteCurrent + do git config receive.deny$deny false + done + "$@" + for deny in CurrentBranch # DeleteCurrent + do git config receive.deny$deny true + done + ) +} + +if [ "$GIT_NAMESPACE" ] +then + GIT_DIR=$dir with_allowCurrentBranch "$cmd" "$dir" +else + "$cmd" "$dir" +fi diff --git a/src/AuthorizedKeysCommand b/src/AuthorizedKeysCommand new file mode 100755 index 0000000..6e13063 --- /dev/null +++ b/src/AuthorizedKeysCommand @@ -0,0 +1,15 @@ +#!/bin/sh +username=$1 +userhome=$2 +fingerprint=$3 +authline="$4 $5" + +case "$userhome" in + *'"'*) exit ;; +esac + +usercommand=$userhome/.ssh/AnonymousAccessCommand + +[ -x "$usercommand" ] || exit + +printf 'command="%s",no-port-forwarding %s\n' "$usercommand $fingerprint" "$authline" diff --git a/src/anonymous-access.conf b/src/anonymous-access.conf new file mode 100644 index 0000000..5cd6b6a --- /dev/null +++ b/src/anonymous-access.conf @@ -0,0 +1,10 @@ +ExposeAuthInfo=yes +AuthorizedKeysCommandUser=root +AuthorizedKeysCommand=/etc/ssh/AuthorizedKeysCommand %u %h %f "%t %k" + +# %u The username. +# %h The home directory of the user. +# %f The fingerprint of the key or certificate. +# %t The key or certificate type. +# %k The base64-encoded key or certificate for authentication. + diff --git a/src/tests.sh b/src/tests.sh new file mode 100644 index 0000000..5d221b6 --- /dev/null +++ b/src/tests.sh @@ -0,0 +1,66 @@ +#!/bin/sh +set -ex +USER=u +DIR=src/anonymous-ssh +HOST=localhost +SSH_ID=~/.ssh/id_ed25519 + +get_sshfp() +{ + ( + key="$1" + r="${2:-.}" + dns=$(mktemp) || exit + trap 'rm -rf "$dns"' EXIT + + ssh-keygen -r "$r" -f "$key" > "$dns" + exec < "$dns" + while read line + do + set -- $line + if [ "$3 $5" = "SSHFP 2" ] + then + echo "$line" + break + fi + done + ) +} + +make_test_commit() +{ + newfile=newfile.$(date -Ins|tr -d :) + touch "$newfile" + git add "$newfile" + git commit -m "$newfile" +} + +[ -e "$SSH_ID" ] || ssh-keygen -t ed25519 -f "$SSH_ID" -P '' + +git_namespace=$(set -- $(get_sshfp "$SSH_ID") && echo $6) + +ssh -o NoHostAuthenticationForLocalhost=yes $USER@$HOST -- test || true +[ ! -e anonymous-ssh ] || rm -rf anonymous-ssh +export GIT_SSH_COMMAND="ssh -o NoHostAuthenticationForLocalhost=yes -i $SSH_ID" +git clone -v ${USER}@${HOST}:${DIR} +cd anonymous-ssh + +make + +git pull --ff-only +make_test_commit +git push -f +make_test_commit +git push +git log -n4 +git pull --ff-only +git log -n4 +git push + +# branch=$(git branch -q --show-current) +# forkname=origin-myfork +# ns_branch=refs/namespaces/$git_namespace/refs/heads/$branch +# git remote add -m "$ns_branch" "$forkname" $(git remote get-url origin) +# git push "$forkname" +# git pull "$forkname" --ff-only "$branch" +exit diff --git a/tests.makefile b/tests.makefile index b152f01..81c9312 100644 --- a/tests.makefile +++ b/tests.makefile @@ -11,7 +11,7 @@ useradd: $(SU) - $(testuser) -c 'git config --global user.email $(testuser)' test: install $(shell getent passwd $(testuser) >/dev/null || echo useradd) - $(ROOT_INSTALL) -t ~$(testuser) tests.sh + $(ROOT_INSTALL) -t ~$(testuser) $(SRC)/tests.sh $(SU) - $(testuser) -c ./tests.sh ifeq ($(testuser),) diff --git a/tests.sh b/tests.sh deleted file mode 100644 index 5d221b6..0000000 --- a/tests.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -set -ex -USER=u -DIR=src/anonymous-ssh -HOST=localhost -SSH_ID=~/.ssh/id_ed25519 - -get_sshfp() -{ - ( - key="$1" - r="${2:-.}" - dns=$(mktemp) || exit - trap 'rm -rf "$dns"' EXIT - - ssh-keygen -r "$r" -f "$key" > "$dns" - exec < "$dns" - while read line - do - set -- $line - if [ "$3 $5" = "SSHFP 2" ] - then - echo "$line" - break - fi - done - ) -} - -make_test_commit() -{ - newfile=newfile.$(date -Ins|tr -d :) - touch "$newfile" - git add "$newfile" - git commit -m "$newfile" -} - -[ -e "$SSH_ID" ] || ssh-keygen -t ed25519 -f "$SSH_ID" -P '' - -git_namespace=$(set -- $(get_sshfp "$SSH_ID") && echo $6) - -ssh -o NoHostAuthenticationForLocalhost=yes $USER@$HOST -- test || true -[ ! -e anonymous-ssh ] || rm -rf anonymous-ssh -export GIT_SSH_COMMAND="ssh -o NoHostAuthenticationForLocalhost=yes -i $SSH_ID" -git clone -v ${USER}@${HOST}:${DIR} -cd anonymous-ssh - -make - -git pull --ff-only -make_test_commit -git push -f -make_test_commit -git push -git log -n4 -git pull --ff-only -git log -n4 -git push - -# branch=$(git branch -q --show-current) -# forkname=origin-myfork -# ns_branch=refs/namespaces/$git_namespace/refs/heads/$branch -# git remote add -m "$ns_branch" "$forkname" $(git remote get-url origin) -# git push "$forkname" -# git pull "$forkname" --ff-only "$branch" -exit -- cgit v1.2.3