- Authenticated push to repo !
TODO:
- - Pulling from anyone using a commit hash ?
+ - Pulling from anyone, using a commit hash ?
- DHT to figure out who has what commits ?
- Question of trust for pulling from peers ?
- The client decyphers and hashes the passphrase, and sends the hash back.
- This avoids the request by a malicious server of decyphering of arbitrary strings.
- The server checks the correctness of the hash.
+ PS: The authentication protocol should be extensible in a backwards-compatible way, should there be a need.
match($0, /(([^@]*)@)?([^/]*)(\/.*)?/, a) { printf "%s\n%s\n%s\n", a[2], a[3], a[4] }
' | { read -r username && read -r gnsname && read -r path && ! grep '.'; }
if test "$?" != "0"; then
- echo >&2 "Invalid address: \`$2'."
- echo >&2 "URI format: \`[gnunet://][user@]gns.name[/path/to/repo]'."
+ echo >&2 "Invalid URI: \`$2'."
+ echo >&2 "Format: \`[gnunet://][user@]gns.name[/path/to/repo]'."
exit 1
fi
-pkey="$(gnunet-identity -qde "$username")"
while read -r cmd arg; do
case "$cmd" in
- capabilities)
- echo 'connect'
- echo ''
- ;;
- connect)
- break
- ;;
- *)
- echo >&2 "Error !"
- exit 1
+ capabilities) printf '%s\n' 'connect' '' ;;
+ connect) break ;;
+ *) echo >&2 "Error: Git remote helper protocol."; exit 1 ;;
esac
done
ip="$(gnunet-vpn -s "$service" -p "$peer" -t)"
echo >&2 "Using tunnel ip \`$ip'."
-case "$username" in
-"")
- { printf '%s\n' "$path" "$arg" "$pkey"; cat; } | socat stdio tcp4:"$ip":9418
- ;;
-*)
- fifo="$(mktemp -u)"
- mkfifo "$fifo" || { echo 2>&1 "Failed to create the fifo."; exit 1; }
- { printf '%s\n' "$path" "$arg" "$pkey"; head -n1 "$fifo"; cat; } \
- | socat stdio tcp4:"$ip":9418 \
- | { head -n 1 \
- | { xargs gnunet-identity -e "$username" -R || { echo >&2 'Error !'; exit 1; }; } \
- | sha256sum > "$fifo";
- cat; }
- rm "$fifo"
- ;;
-esac
+fifo="$(mktemp -u "git-over-gnunet.XXXXXXXXXX" --tmpdir)"
+mkfifo "$fifo" || { echo 2>&1 "Failed to create the fifo."; exit 1; }
+{
+ test "" = "$username" || pkey="$(gnunet-identity -qde "$username")" || { echo 2>&1 "Failed to get pkey for username \`$username'."; rm "$fifo"; exit 1; }
+ printf '%s\n' "Path:$path" "Command:$arg" "Key:$pkey";
+ echo;
+ cat "$fifo" -;
+} | socat stdio tcp4:"$ip":9418 | {
+ { if test "" != "$username"; then
+ read -r cyphertext
+ case "$cyphertext" in
+ "Error: "*)
+ echo >&2 "$cyphertext"
+ rm "$fifo"
+ exit 1
+ ;;
+ "Key:"*)
+ plaintext="$(gnunet-identity -e "$username" -R "${cyphertext:4}")" || { rm "$fifo"; exit 1; }
+ printf '%s\n' "$plaintext" | sha256sum
+ ;;
+ esac;
+ fi; } > "$fifo";
+ cat;
+}
+rm "$fifo"
base_path="$1"
pkeys="$2"
-read -r path || { echo "No path specified." | tee /dev/stderr; exit 1; }
-read -r comm || { echo "No command specified." | tee /dev/stderr; exit 1; }
-read -r pkey || { echo "No pkey specified." | tee /dev/stderr; exit 1; }
+while read -r line; do
+ case "$line" in
+ "Path:"*) path="${line:5}" ;;
+ "Command:"*) comm="${line:8}" ;;
+ "Key:"*) pkey="${line:4}" ;;
+ "") break ;;
+ *) echo "Error: Unknown information key: \`$line'."; exit ;;
+ esac
+done
full_path="$(realpath -sm "$base_path$path")"
case "$full_path" in
"$base_path") ;;
"$base_path/"*) ;;
-*) echo "Invalid path: \`$full_path'." | tee /dev/stderr
- exit 1
+*) echo "Error: Invalid path: \`$full_path'."
+ exit
;;
esac
if test "" != "$pkey"; then
- pkey="$(grep -xm1 -- "$pkey" < "$pkeys")" || { echo "Unknown public key." | tee /dev/stderr; exit 1; }
+ grep -qxF -- "$pkey" "$pkeys" || { echo "Error: Unknown public key."; exit; }
keyphrase="$(</dev/random base64 2> /dev/null | head -c 64)"
hashed="$(printf '%s\n' "$keyphrase" | sha256sum)"
encrypted="$(gnunet-identity -k "$pkey" -W "$keyphrase")"
- printf '%s\n' "$encrypted"
+ printf 'Key:%s\n' "$encrypted"
read -r returned_hash
case "$returned_hash" in
- "$hashed")
- ;;
- *)
- echo "Incorrect passphrase decryption." | tee /dev/stderr
- exit 1
- ;;
+ "$hashed") ;;
+ *) echo "Error: Incorrect passphrase decryption."; exit ;;
esac
fi
case "$comm" in
-git-upload-pack)
- # Unidentified pull is allowed.
- ;;
-git-receive-pack)
- if test "" = "$pkey"; then
- echo "Unidentified push is not allowed." | tee /dev/stderr
- exit 1
- fi
- ;;
-*)
- echo "Unknown command: \`$comm'." | tee /dev/stderr
- exit 1
- ;;
+git-upload-pack) ;; # Unidentified pull is allowed.
+git-receive-pack) test "" = "$pkey" && { echo "Error: Unidentified push is not allowed."; exit; } ;;
+*) echo "Error: Unknown command: \`$comm'."; exit ;;
esac
-git_dir="$(git -C "$full_path" rev-parse --path-format=absolute --git-dir)" || { echo "Not a git repository: \`$full_path'." | tee /dev/stderr; exit 1; }
+git_dir="$(git -C "$full_path" rev-parse --path-format=absolute --git-dir)" || { echo "Error: Not a git repository: \`$full_path'."; exit; }
echo ''
exec "$comm" "$git_dir"