]> git.ameliathe1st.gay Git - git-over-gnunet.git/commitdiff
Rewrite using gnunet-vpn
authorAmélia Coutard-Sander <git@ameliathe1st.gay>
Mon, 2 Dec 2024 21:07:38 +0000 (22:07 +0100)
committerAmélia Coutard-Sander <git@ameliathe1st.gay>
Mon, 2 Dec 2024 21:07:38 +0000 (22:07 +0100)
README.txt
daemon.sh [deleted file]
git-remote-gnunet
handle-request.sh [new file with mode: 0755]
run-daemons.sh [deleted file]

index c9eadbe27fb26191c888441579be5adcd4654aae..59e784f5c05ed9845c6e1e6b56a6d08ebd098a36 100644 (file)
@@ -1,18 +1,27 @@
-This set of bash scripts allows one to clone/fetch/pull git repositories using gnunet, specifically the GNS and cadet.
-In the interest of demonstrating that it works, this repo is available at
-       `gnunet://git.serv.amelia.gnunet.gns.alt/git-over-gnunet`.
-       Try cloning it ! (And do tell me if it fails, or if it works.)
+This set of bash scripts allows one to clone/fetch/pull git repositories using gnunet, specifically the GNS and the GNUnet VPN.
+In the interest of demonstrating that it works, all the repos on my server are available at
+       `gnunet://git.serv.amelia.gnunet.gns.alt/<repo>.git` (see gitweb for the specific URIs).
+       Try cloning them ! (And do tell me if it fails, or if it works.)
 
 Usage:
 Client:
        You must add the repo folder to the GIT_EXEC_PATH (for example by prepending
                `GIT_EXEC_PATH=$GIT_EXEC_PATH:<path-to-git-over-gnunet-repo>` before every git command that uses remotes).
-       The URL to give to git is gnunet://<location of the repo>/<name of the repo>.
+       The URL to give to git is `gnunet://<gns location of the repo>/<name of the repo>`.
 Server:
-       - To run the server on a repo, simply copy the two .sh files to its root's parent, and run
-               `./run-daemons.sh <repo-name>`.
-       - You should also add a gns TXT record containing the peerid serving your repos to your zone.
-       - This will open the repo for pulling on the url `gnunet://<gns-record-name>/<repo-name>`.
+       - To serve repos, you have to setup a gnunet-vpn exit service.
+         ```
+         [exit]
+         IMMEDIATE_START = YES
+         EXIT_IFNAME = %
+         [<gns-name>.gnunet.]
+         TCP_REDIRECTS = 9418:169.254.86.1:9418
+         ```
+       - You should also add a gns VPN record containing the required information to connect to the exit service.
+         `gnunet-namestore -a -t VPN -e 1d -n <gns-name> -V '1 <peer-id> <gns-name>' -z <ego> -p`
+       - Next, you need to run the daemon: it needs to run `handle-request.sh` in the parent folder of all the repos every time someone connects to it.
+         For example, with socat: `socat tcp4-listen:9418,bind=169.254.86.1,fork  exec:'/path/to/handle-request.sh /path/to/repos'`
+       - This will open the repos for pulling on the url `gnunet://<gns-record-name>/<repo-name>`.
 
 Features:
        - Clone repo !
@@ -20,23 +29,17 @@ Features:
        - Pull repo !
 
 TODO:
-       - GNUnet VPN exit service
-       - Figure out why cadet breaks when pushing, probably linked to the usage of the CLI client, GNUnet VPN rewrite might fix.
-               - gnunet-cadet exits too early, definitely an issue with the input method. GNUnet VPN will probably fix the issue.
-               In the meantime, a cat+sleep is a reasonnable enough "fix".
-       - In which case, password system to push to repos (just add the password to the port ?)
+       - Pushing, and a gnunet-identity verification system ?
        - Pulling from anyone using a commit hash ?
                - DHT to figure out who has what commits ?
                - Question of trust for pulling from peers ?
-       - Multiple repos.
 
 How it works:
 Client:
        - Uses a git remote helper to give git the ability to interpet the gnunet:// scheme.
-       - Gets the TXT record associated with the GNS name given in gnunet://<gns-name>/<repo-name>.
-       - This TXT record is a <peer-id>.
-       - To run a specific git command on repo <repo> and get its inputs and outputs, connect via cadet
-               to the peer id <peer-id>, via the port git.<repo-name>-<command>.
-       - This is used by the remote helper to run git-upload-pack remotely.
+       - Gets the VPN record associated with the GNS name given in gnunet://<gns-name>/<repo-name>.
+       - Connects to the exit service, give it the name of the repo and the command required (e.g. `git-upload-pack`).
 Server:
-       - The server just loops on a cadet server with inputs and outputs connected to the specified git-command.
+       - Reads the path and the command.
+       - Checks that the command is git-upload-pack and the path isn't malicious.
+       - Executes the command and connects it to the client.
diff --git a/daemon.sh b/daemon.sh
deleted file mode 100755 (executable)
index 0720812..0000000
--- a/daemon.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-
-mktempfifo() {
-       fifo_name="$(mktemp -u)"
-       mkfifo "$fifo_name" || mktempfifo
-}
-
-if test -z $1 || test -z $2 || ! test -z $3; then
-       echo >&2 "Usage: $0 <service> <name>"
-       exit 1
-fi
-
-service="$1"
-name="$2"
-
-echo >&2 "Running $service on port \`git.$name.git-$service'."
-
-mktempfifo
-while < "$fifo_name" gnunet-cadet -o "git.$name.git-$service" | git "$service" "$(pwd)/$name" | (cat; sleep 5) | cat > "$fifo_name"; test 130 != "$?"; do
-       rm "$fifo_name"
-       mktempfifo
-done
-
-rm $fifo_name
-
-echo >&2 "Terminating $service on port \`git.$name.git-$service'."
index c92e29d7ddf5269f409cbe1acb01c288a2f6501e..59d1bcd19793b8831831d9845265fe0e9a89e5b9 100755 (executable)
@@ -1,20 +1,20 @@
 #!/usr/bin/env bash
 
+shopt -s lastpipe
+
 if [[ "$2" = gnunet://* ]]; then
-       addr=${2:9}
+       echo "${2:9}"
 else
-       addr=$2
-fi
-gns="$(echo "$addr" | cut -d/ -f1)"
-repo="$(echo "$addr" | cut -d/ -f2)"
-if test -z "$gns" || test -z "$repo" || ! test -z "$(echo "$addr" | cut -d/ -f3-)"; then
+       echo "$2"
+fi | awk '
+match($0, /(([^@]*)@)?([^/]*)(\/(.*))?/, a) { printf "%s\n%s\n%s\n", a[2], a[3], a[5] }
+' | { read -r username && read -r gnsname && read -r path && ! grep '.'; }
+if test "$?" != "0"; then
        echo >&2 "Invalid address: \`$2'."
-       echo >&2 "Format: \`gnunet://gns-name/repo-name'."
-       echo >&2 "     or \`gnunet::gns-name/repo-name'."
+       echo >&2 "URI format: \`[gnunet://][user@]gns.name/path/to/repo'."
        exit 1
 fi
 
-
 while read -r cmd arg; do
        case "$cmd" in
        capabilities)
@@ -30,18 +30,16 @@ while read -r cmd arg; do
        esac
 done
 
-if [[ "$arg" = "git-receive-pack" ]]; then
-       echo >&2 "Pushing unsupported for now."
+echo >&2 "Looking up $gnsname."
+vpn="$(gnunet-gns -u "$gnsname" -t VPN -r)"
+if test "$(echo "$vpn" | cut -d' ' -f1)" != "1"; then
+       echo >&2 "VPN record must specify TCP, not UDP."
        exit 1
 fi
+peer="$(echo "$vpn" | cut -d' ' -f2)"
+service="$(echo "$vpn" | cut -d' ' -f3)"
+echo >&2 "Trying service \`$service' on peer \`$peer'."
+ip="$(gnunet-vpn -s "$service" -p "$peer" -t)"
+echo >&2 "Using tunnel ip \`$ip'."
 
-echo ''
-echo >&2 "Looking up $gns."
-peer="$(gnunet-gns -u "$gns" -t TXT -r)"
-if test -z "$peer"; then
-       echo >&2 "Address lookup failed: \`$gns'."
-       exit 1
-fi
-port="git.$repo.$arg"
-echo >&2 "Attempting to connect to peer $peer, on port \`$port'."
-(stdbuf -i0 -o0 -e0 cat; sleep 0.01) | gnunet-cadet "$peer" "$port"
+{ printf '%s\n' "$path" "$arg"; cat; } | socat stdio tcp4:"$ip":9418
diff --git a/handle-request.sh b/handle-request.sh
new file mode 100755 (executable)
index 0000000..32785ed
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+if test -z $1 || ! test -z $2; then
+       echo >&2 "Usage: $0 /base/path"
+       exit 1
+fi
+base_path="$1/"
+
+read -r path || { echo "No path specified." | tee /dev/stderr; exit 1; }
+read -r comm || { echo "No command specified." | tee /dev/stderr; exit 1; }
+
+if echo "$path" | grep -q '/'; then
+       echo "Path \`$path' contains a '/'." | tee /dev/stderr
+       exit 1
+fi
+if test "$path" = '..'; then
+       echo "Path cannot be \`..'." | tee /dev/stderr
+       exit 1
+fi
+
+if test "$comm" != "git-upload-pack"; then
+       echo "Command \`$comm' has to be git-upload-pack." | tee /dev/stderr
+       exit 1
+fi
+
+git -C "$base_path$path" status >/dev/null 2>/dev/null || { echo "Not a git repository." | tee /dev/stderr; exit 1; }
+
+echo ''
+exec "$comm" "$base_path$path"
diff --git a/run-daemons.sh b/run-daemons.sh
deleted file mode 100755 (executable)
index db1302d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-if test -z $1 || ! test -z $2; then
-       echo >&2 "Usage: $0 <repo-name>"
-       exit 1
-fi
-
-name="$1"
-
-echo >&2 "Running pullable repo $name."
-
-./daemon.sh upload-pack "$name"
-
-echo >&2 "Terminating pullable repo $name."