blob: 082f185e8d26d9d3825aebfe08d07a42b5e765af (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/bin/sh
default_msg()
{
sshfpline="$(get_sshfp_authline ${SSH_CLIENT%% *})"
cat <<EOF >&2
You are:
$authline
$sshfpline
EOF
}
not_self_forge_message()
{
cat <<EOF >&2
Error: access denied. The specified directory is not a self-forge.
To enable anonymous access, use the following commands:
ssh $(id -un)@$(hostname)
cd "$1"
git config core.self-forge true
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
}
is_self_forge()
{
local dir="$1" confval
[ -d "$dir" ] || return
confval=$(GIT_DIR=$dir git config core.self-forge) || return
[ "$confval" = true ]
}
with_soul_bare()
{
(
set -eC
lockfile=$GIT_DIR/index.lock
echo $$ > "$lockfile"
trap 'rm -f "$lockfile"' EXIT
git config core.bare true
"$@"
git config core.bare false
)
}
unsupported()
{
echo "$0: Error: unsupported" >&2
}
read authtype authline < "$SSH_USER_AUTH" || exit
[ "$authtype" = publickey ] || exit
cmd=${SSH_ORIGINAL_COMMAND%% *}
case "$cmd" in
git-send-pack | git-upload-pack | git-receive-pack ) ;;
* )
default_msg
exit
;;
esac
arg=${SSH_ORIGINAL_COMMAND#* }
arg=${arg%\'}
arg=${arg#\'}
case "$arg" in
*\'* )
unsupported
exit
;;
esac
if ! dir=$(readlink -e "$arg")
then exit
elif [ -d "$dir"/.git ]
then dir=$dir/.git
fi
if ! is_self_forge "$dir"
then
not_self_forge_message "$arg"
exit
fi
case "$cmd" in
git-send-pack | git-upload-pack )
GIT_NAMESPACE=
"$cmd" "$dir"
;;
git-receive-pack )
export GIT_NAMESPACE="$(ssh_client_fingerprint_base16)"
[ "$GIT_NAMESPACE" ]
GIT_DIR=$dir with_soul_bare "$cmd" "$dir"
;;
esac
|