diff options
Diffstat (limited to 'src/samizdat-ssh-command')
-rwxr-xr-x | src/samizdat-ssh-command | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/src/samizdat-ssh-command b/src/samizdat-ssh-command index 94679f2..79053fd 100755 --- a/src/samizdat-ssh-command +++ b/src/samizdat-ssh-command | |||
@@ -1,12 +1,21 @@ | |||
1 | #!/bin/dash | 1 | #!/bin/dash |
2 | default_command="$HOME/samizdat-default-command" | ||
3 | if ! [ "$default_command" ] || ! [ -e "$default_command" ] | ||
4 | then | ||
5 | default_command=password_authentication | ||
6 | fi | ||
7 | |||
2 | authorize() | 8 | authorize() |
3 | { | 9 | { |
4 | local pkey line authorized_keys_line cmd | 10 | local authtype authdata forced_command comment authorized_keys_line |
5 | [ "$SSH_USER_AUTH" -a -f "$SSH_USER_AUTH" ] || return | 11 | [ "$SSH_USER_AUTH" -a -f "$SSH_USER_AUTH" ] || return |
6 | read pkey line < "$SSH_USER_AUTH" || return | 12 | read authtype authdata < "$SSH_USER_AUTH" || return |
7 | [ "$pkey" = publickey ] || return | 13 | [ "$authtype" = publickey ] || return |
14 | |||
15 | forced_command="command=\"${0} authorize-full-access\",no-port-forwarding" | ||
16 | comment="samizdat: password-authenticated from ${SSH_CONNECTION%% *}" | ||
8 | 17 | ||
9 | authorized_keys_line="$line samizdat: password-authenticated from ${SSH_CONNECTION%% *}" | 18 | authorized_keys_line="$forced_command $authdata $comment" |
10 | sentinel='Samizdat - YES WE CAN' | 19 | sentinel='Samizdat - YES WE CAN' |
11 | 20 | ||
12 | su - "$USER" -c 'mkdir -p "$HOME"/.ssh; touch "$HOME"/.ssh/authorized_keys' && | 21 | su - "$USER" -c 'mkdir -p "$HOME"/.ssh; touch "$HOME"/.ssh/authorized_keys' && |
@@ -14,6 +23,7 @@ authorize() | |||
14 | "$authorized_keys_line" \ | 23 | "$authorized_keys_line" \ |
15 | "$HOME"/.ssh/authorized_keys | 24 | "$HOME"/.ssh/authorized_keys |
16 | } | 25 | } |
26 | |||
17 | add_before_sentinel() | 27 | add_before_sentinel() |
18 | { | 28 | { |
19 | local sentinel="$1" add_me="$2" target="$3" | 29 | local sentinel="$1" add_me="$2" target="$3" |
@@ -25,7 +35,7 @@ add_before_sentinel() | |||
25 | password_authentication() | 35 | password_authentication() |
26 | { | 36 | { |
27 | [ "$USER" ] || { echo 'Error: no $USER' >&2; exit 1; } | 37 | [ "$USER" ] || { echo 'Error: no $USER' >&2; exit 1; } |
28 | [ "$SSH_REMOTE_KEY" ] || { echo 'Error: no $SSH_REMOTE_KEY' >&2; exit 1; } | 38 | [ "$SSH_CLIENT_FINGERPRINT" ] || { echo 'Error: no $SSH_CLIENT_FINGERPRINT' >&2; exit 1; } |
29 | 39 | ||
30 | tty=$(tty) && [ "$tty" != 'not a tty' ] || tty= | 40 | tty=$(tty) && [ "$tty" != 'not a tty' ] || tty= |
31 | 41 | ||
@@ -143,7 +153,7 @@ valid_new_public_repo() | |||
143 | 153 | ||
144 | check_if_ssh_user_owns_repository() | 154 | check_if_ssh_user_owns_repository() |
145 | { | 155 | { |
146 | git --git-dir "$git_dir" config --get-all samizdat.anonymous-ssh-owner | grep -xqF "$SSH_REMOTE_FINGERPRINT_TRIMMED" | 156 | git --git-dir "$git_dir" config --get-all samizdat.anonymous-ssh-owner | grep -xqF "$SSH_CLIENT_FINGERPRINT" |
147 | } | 157 | } |
148 | ssh_user_owns_repository() | 158 | ssh_user_owns_repository() |
149 | { | 159 | { |
@@ -165,11 +175,11 @@ is_public_repository() | |||
165 | 175 | ||
166 | authorized() | 176 | authorized() |
167 | { | 177 | { |
168 | # TODO: check SSH_REMOTE_FINGERPRINT against a blacklist | 178 | # TODO: check SSH_CLIENT_FINGERPRINT against a blacklist |
169 | ssh_user_owns_repository && return | 179 | ssh_user_owns_repository && return |
170 | is_public_repository && return | 180 | is_public_repository && return |
171 | test "$(git --git-dir "$1" config --bool --get samizdat.allow-anonymous-access)" = true 2>/dev/null && return 0 | 181 | test "$(git --git-dir "$1" config --bool --get samizdat.allow-anonymous-access)" = true 2>/dev/null && return 0 |
172 | # TODO: check SSH_REMOTE_FINGERPRINT against a whitelist | 182 | # TODO: check SSH_CLIENT_FINGERPRINT against a whitelist |
173 | } | 183 | } |
174 | 184 | ||
175 | maybe_initialize_heads() | 185 | maybe_initialize_heads() |
@@ -197,31 +207,20 @@ if [ "$1" = "authorize-full-access" ]; then | |||
197 | "") | 207 | "") |
198 | shell=$(getent passwd $USER|cut -d: -f7) | 208 | shell=$(getent passwd $USER|cut -d: -f7) |
199 | argv0=-${shell##*/} | 209 | argv0=-${shell##*/} |
200 | exec chpst -b "$argv0" "$shell" | 210 | if which chpst >/dev/null 2>&1; then |
211 | exec chpst -b "$argv0" "$shell" | ||
212 | else | ||
213 | exec "$shell" | ||
214 | fi | ||
201 | ;; | 215 | ;; |
202 | *) | 216 | *) |
203 | exec /bin/sh -c "$SSH_ORIGINAL_COMMAND" | 217 | exec /bin/sh -c "$SSH_ORIGINAL_COMMAND" |
204 | ;; | 218 | ;; |
205 | esac | 219 | esac |
220 | exit | ||
206 | fi | 221 | fi |
207 | 222 | ||
208 | 223 | eval "$(samizdat-ssh-uid)" || die eval | |
209 | (exec >&2 | ||
210 | #env | grep '^SSH_' | ||
211 | #cat "${SSH_USER_AUTH}" | ||
212 | #ssh-keygen -l -f "${SSH_USER_AUTH}" | ||
213 | #sed -i -e 's/^publickey //' "${SSH_USER_AUTH}" | ||
214 | #set -x | ||
215 | #ssh-keygen -r . -f "${SSH_USER_AUTH}" | sed -ne 's/^. IN SSHFP [0-9]* 1 /SHA1:/p' | ||
216 | ) | ||
217 | |||
218 | USE_MD5_SIG= | ||
219 | if [ "$USE_MD5_SIG" ]; then | ||
220 | SSH_REMOTE_FINGERPRINT_TRIMMED=$(echo $SSH_REMOTE_FINGERPRINT|tr -d :) | ||
221 | else | ||
222 | sed -i -e 's/^publickey //' "${SSH_USER_AUTH}" || die "error rewriting SSH_USER_AUTH file" | ||
223 | SSH_REMOTE_FINGERPRINT_TRIMMED=$(ssh-keygen -r . -f "${SSH_USER_AUTH}" | sed -ne 's/^. IN SSHFP [0-9]* 1 //p') | ||
224 | fi | ||
225 | 224 | ||
226 | # TODO: call password_authentication on all authorization failures | 225 | # TODO: call password_authentication on all authorization failures |
227 | 226 | ||
@@ -262,14 +261,15 @@ case "$SSH_ORIGINAL_COMMAND" in | |||
262 | exit 1 | 261 | exit 1 |
263 | ;; | 262 | ;; |
264 | rsync\ --server\ *) | 263 | rsync\ --server\ *) |
265 | [ -d "$HOME"/incoming_rsync -a "${SSH_REMOTE_FINGERPRINT_TRIMMED}" ] || { password_authentication; exit 1; } | 264 | [ -d "$HOME"/incoming_rsync -a "${SSH_CLIENT_FINGERPRINT}" ] || { password_authentication; exit 1; } |
266 | destdir=$HOME/incoming_rsync/$SSH_REMOTE_FINGERPRINT_TRIMMED/ | 265 | destdir=$HOME/incoming_rsync/$SSH_CLIENT_FINGERPRINT/ |
267 | mkdir -p "$destdir" && exec rrsync "$destdir" | 266 | mkdir -p "$destdir" && exec rrsync "$destdir" |
268 | exit 1 | 267 | exit 1 |
269 | ;; | 268 | ;; |
270 | *) | 269 | *) |
271 | password_authentication | 270 | #password_authentication |
272 | exit 1 # unreached | 271 | $default_command |
272 | exit | ||
273 | ;; | 273 | ;; |
274 | esac | 274 | esac |
275 | 275 | ||
@@ -293,7 +293,7 @@ elif [ "$git_cmd" = 'git-receive-pack' ]; then | |||
293 | 293 | ||
294 | if [ ! -d "$git_dir" ]; then | 294 | if [ ! -d "$git_dir" ]; then |
295 | if valid_new_public_repo "$git_dir"; then | 295 | if valid_new_public_repo "$git_dir"; then |
296 | initialize_git "$git_dir" "$SSH_REMOTE_FINGERPRINT_TRIMMED" | 296 | initialize_git "$git_dir" "$SSH_CLIENT_FINGERPRINT" |
297 | else | 297 | else |
298 | deny | 298 | deny |
299 | fi | 299 | fi |
@@ -305,13 +305,14 @@ if authorized "$git_dir"; then | |||
305 | if [ "$git_cmd" = 'git-receive-pack' ]; then | 305 | if [ "$git_cmd" = 'git-receive-pack' ]; then |
306 | if ! ssh_user_owns_repository | 306 | if ! ssh_user_owns_repository |
307 | then | 307 | then |
308 | export GIT_NAMESPACE="$SSH_REMOTE_FINGERPRINT_TRIMMED" | 308 | export GIT_NAMESPACE="$SSH_CLIENT_FINGERPRINT" |
309 | maybe_initialize_heads | 309 | maybe_initialize_heads |
310 | printf '%s:%s\n' 'd@cryptonomic.net' "git_namespace/$GIT_NAMESPACE/${git_dir#${HOME}/}" >&2 | 310 | printf '%s:%s\n' 'd@cryptonomic.net' "git_namespace/$GIT_NAMESPACE/${git_dir#${HOME}/}" >&2 |
311 | fi | 311 | fi |
312 | fi | 312 | fi |
313 | exec "$git_cmd" "$git_dir" | 313 | exec "$git_cmd" "$git_dir" |
314 | else | 314 | else |
315 | password_authentication | 315 | $default_command |
316 | echo 'Error: git access is unauthorized' >&2; exit 1 # unreached | 316 | exit |
317 | # echo 'Error: git access is unauthorized' >&2; exit 1 # unreached | ||
317 | fi | 318 | fi |