itRemove old code. - tordam - A library for peer discovery inside the Tor network Err parazyd.org 70 hgit clone https://git.parazyd.org/tordam URL:https://git.parazyd.org/tordam parazyd.org 70 1Log /git/tordam/log.gph parazyd.org 70 1Files /git/tordam/files.gph parazyd.org 70 1Refs /git/tordam/refs.gph parazyd.org 70 1README /git/tordam/file/README.md.gph parazyd.org 70 1LICENSE /git/tordam/file/LICENSE.gph parazyd.org 70 i--- Err parazyd.org 70 1commit 2f8bd41a607d578b727c1c8ee20f10b2cebb1bdc /git/tordam/commit/2f8bd41a607d578b727c1c8ee20f10b2cebb1bdc.gph parazyd.org 70 1parent 625b81777d0403bc36ebada9ecafd04071aef6f3 /git/tordam/commit/625b81777d0403bc36ebada9ecafd04071aef6f3.gph parazyd.org 70 hAuthor: parazyd URL:mailto:parazyd@dyne.org parazyd.org 70 iDate: Sun, 7 Mar 2021 20:07:26 +0100 Err parazyd.org 70 i Err parazyd.org 70 iRemove old code. Err parazyd.org 70 i Err parazyd.org 70 iDiffstat: Err parazyd.org 70 i M README.md | 49 +++++-------------------------- Err parazyd.org 70 i D announce.go | 179 ------------------------------- Err parazyd.org 70 i D api.go | 191 ------------------------------- Err parazyd.org 70 i D config.go | 36 ------------------------------- Err parazyd.org 70 i A contrib/tordam.png | 0 Err parazyd.org 70 i D crypto.go | 63 ------------------------------- Err parazyd.org 70 i D helpers.go | 88 ------------------------------- Err parazyd.org 70 i D net.go | 83 ------------------------------- Err parazyd.org 70 i D redis.go | 141 ------------------------------- Err parazyd.org 70 i D tor-dam.go | 191 ------------------------------- Err parazyd.org 70 i D tor.go | 68 ------------------------------- Err parazyd.org 70 i D types.go | 37 ------------------------------- Err parazyd.org 70 i D validate.go | 158 ------------------------------- Err parazyd.org 70 i Err parazyd.org 70 i13 files changed, 8 insertions(+), 1276 deletions(-) Err parazyd.org 70 i--- Err parazyd.org 70 1diff --git a/README.md b/README.md /git/tordam/file/README.md.gph parazyd.org 70 it@@ -1,55 +1,22 @@ Err parazyd.org 70 i tor-dam (Tor Distributed Announce Mechanism) Err parazyd.org 70 i ============================================ Err parazyd.org 70 i Err parazyd.org 70 i-Protocol and tooling for mapping machines in the Tor network running Err parazyd.org 70 i-this software. Err parazyd.org 70 i+![tordam](contrib/tordam.png) Err parazyd.org 70 i Err parazyd.org 70 i-![Network visualization](https://raw.githubusercontent.com/parazyd/tor-dam/master/contrib/network.gif) Err parazyd.org 70 i+A library for peer discovery inside the Tor network. Err parazyd.org 70 i Err parazyd.org 70 i Err parazyd.org 70 i Installation Err parazyd.org 70 i ------------ Err parazyd.org 70 i Err parazyd.org 70 i ``` Err parazyd.org 70 i-go get github.com/parazyd/tor-dam Err parazyd.org 70 i+go get github.com/parazyd/tordam Err parazyd.org 70 i ``` Err parazyd.org 70 i Err parazyd.org 70 i-Usage Err parazyd.org 70 i------ Err parazyd.org 70 i+Documentation Err parazyd.org 70 i+------------- Err parazyd.org 70 i Err parazyd.org 70 i-``` Err parazyd.org 70 i-Usage of ./tor-dam: Err parazyd.org 70 i- -d string Err parazyd.org 70 i- Working directory (default "/home/parazyd/.dam") Err parazyd.org 70 i- -e int Err parazyd.org 70 i- Node expiry time in minutes (0=unlimited) Err parazyd.org 70 i- -g (Re)generate keys and exit Err parazyd.org 70 i- -i int Err parazyd.org 70 i- Announce interval (in minutes) (default 5) Err parazyd.org 70 i- -n Don't fetch remote entrypoints Err parazyd.org 70 i- -p string Err parazyd.org 70 i- Map of ports forwarded to/from Tor (default "13010:13010,13011:13011,5000:5000") Err parazyd.org 70 i- -r string Err parazyd.org 70 i- Remote list of entrypoints (comma-separated) (default "https://parazyd.org/pub/tmp/tor-dam-dirs.txt") Err parazyd.org 70 i- -t Trust all new nodes automatically Err parazyd.org 70 i-``` Err parazyd.org 70 i+https://pkg.go.dev/github.com/parazyd/tordam Err parazyd.org 70 i Err parazyd.org 70 i-Protocol Err parazyd.org 70 i--------- Err parazyd.org 70 i- Err parazyd.org 70 i-* Every node has an HTTP API allowing to list other nodes and announce Err parazyd.org 70 i- new ones. Err parazyd.org 70 i-* They keep propagating to all trusted nodes they know. Err parazyd.org 70 i-* Announcing implies the need of knowledge of at least one node. Err parazyd.org 70 i- * It is possible to make this random enough once there are at least Err parazyd.org 70 i- 6 nodes in the network. Err parazyd.org 70 i-* A node announces itself to others by sending a JSON-formatted HTTP Err parazyd.org 70 i- POST request to one or more active nodes. Err parazyd.org 70 i- * Once the initial POST request is received, the receiving node will Err parazyd.org 70 i- ACK and return a random string (nonce) back to the requester for Err parazyd.org 70 i- them to sign with their cryptographic key. Err parazyd.org 70 i- * The requester will try to sign this nonce and return it back to Err parazyd.org 70 i- the node it's announcing to, so the node can confirm the requester Err parazyd.org 70 i- is in actual posession of the private key. Err parazyd.org 70 i-* tor-dam **does not validate** if a node should be trusted or not. Err parazyd.org 70 i- This is a layer that has to be implemented with external software. Err parazyd.org 70 i+tor-dam is a small library that can be used to facilitate peer to peer Err parazyd.org 70 i+services in the Tor network with simple mechanisms. Err parazyd.org 70 1diff --git a/announce.go b/announce.go /git/tordam/file/announce.go.gph parazyd.org 70 it@@ -1,179 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "bytes" Err parazyd.org 70 i- "compress/gzip" Err parazyd.org 70 i- "crypto/ed25519" Err parazyd.org 70 i- "crypto/rand" Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "encoding/json" Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "math/big" Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func fetchNodeList(epLists []string, remote bool) ([]string, error) { Err parazyd.org 70 i- var ns, nl []string Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Building a list of nodes") Err parazyd.org 70 i- Err parazyd.org 70 i- // Remote network entrypoints Err parazyd.org 70 i- if !remote { Err parazyd.org 70 i- for _, i := range epLists { Err parazyd.org 70 i- log.Println("Fetching", i) Err parazyd.org 70 i- n, err := httpGet(i) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- ns = parseDirs(ns, n) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Local workdir/dirs.txt Err parazyd.org 70 i- ld := strings.Join([]string{*workdir, "dirs.txt"}, "/") Err parazyd.org 70 i- if _, err := os.Stat(ld); err == nil { Err parazyd.org 70 i- ln, err := ioutil.ReadFile(ld) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- ns = parseDirs(ns, ln) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Local nodes from redis Err parazyd.org 70 i- nodes, _ := rcli.Keys(rctx, "*.onion").Result() Err parazyd.org 70 i- for _, i := range nodes { Err parazyd.org 70 i- valid, err := rcli.HGet(rctx, i, "valid").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- // Possible RedisCli bug, possible Redis bug. To be investigated. Err parazyd.org 70 i- // Sometimes it returns err, but it's empty and does not say what's Err parazyd.org 70 i- // happening exactly. Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- if valid == "1" { Err parazyd.org 70 i- ns = append(ns, i) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Remove possible dupes. Duplicates can cause race conditions and are Err parazyd.org 70 i- // redundant to the entire logic. Err parazyd.org 70 i- // TODO: Work this in above automatically (by changing the var type) Err parazyd.org 70 i- encounter := map[string]bool{} Err parazyd.org 70 i- for i := range ns { Err parazyd.org 70 i- encounter[ns[i]] = true Err parazyd.org 70 i- } Err parazyd.org 70 i- ns = []string{} Err parazyd.org 70 i- for key := range encounter { Err parazyd.org 70 i- ns = append(ns, key) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if len(ns) < 1 { Err parazyd.org 70 i- log.Fatal("Couldn't find any nodes to announce to. Exiting...") Err parazyd.org 70 i- } else if len(ns) <= 6 { Err parazyd.org 70 i- log.Printf("Found %d nodes\n", len(ns)) Err parazyd.org 70 i- nl = ns Err parazyd.org 70 i- } else { Err parazyd.org 70 i- log.Printf("Found %d nodes. Picking out 6 at random\n", len(ns)) Err parazyd.org 70 i- for i := 0; i <= 5; i++ { Err parazyd.org 70 i- n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(ns)))) Err parazyd.org 70 i- nl = append(nl, ns[n.Int64()]) Err parazyd.org 70 i- ns[n.Int64()] = ns[len(ns)-1] Err parazyd.org 70 i- ns = ns[:len(ns)-1] Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return nl, nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func announce(addr string, vals map[string]string) (bool, error) { Err parazyd.org 70 i- msg, _ := json.Marshal(vals) Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Announcing keypair to", addr) Err parazyd.org 70 i- resp, err := httpPost("http://"+addr+":49371"+"/announce", msg) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Parse server's reply Err parazyd.org 70 i- var m Message Err parazyd.org 70 i- dec := json.NewDecoder(resp.Body) Err parazyd.org 70 i- if err := dec.Decode(&m); err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if resp.StatusCode != 200 { Err parazyd.org 70 i- log.Printf("%s returned error: %s\n", addr, m.Secret) Err parazyd.org 70 i- return false, nil Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Got nonce from", addr) Err parazyd.org 70 i- Err parazyd.org 70 i- sig := ed25519.Sign(signingKey, []byte(m.Secret)) Err parazyd.org 70 i- Err parazyd.org 70 i- vals["secret"] = m.Secret Err parazyd.org 70 i- vals["message"] = m.Secret Err parazyd.org 70 i- vals["signature"] = base64.StdEncoding.EncodeToString(sig) Err parazyd.org 70 i- msg, _ = json.Marshal(vals) Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Sending back signed secret to", addr) Err parazyd.org 70 i- resp, err = httpPost("http://"+addr+":49371"+"/announce", msg) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- dec = json.NewDecoder(resp.Body) Err parazyd.org 70 i- if err := dec.Decode(&m); err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if resp.StatusCode != 200 { Err parazyd.org 70 i- log.Printf("%s returned error: %s\n", addr, m.Secret) Err parazyd.org 70 i- return false, nil Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Printf("%s handshake valid\n", addr) Err parazyd.org 70 i- data, err := base64.StdEncoding.DecodeString(m.Secret) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- // Not a list of nodes Err parazyd.org 70 i- log.Printf("%s replied: %s\n", addr, m.Secret) Err parazyd.org 70 i- return true, nil Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Got node data, processing...") Err parazyd.org 70 i- b := bytes.NewReader(data) Err parazyd.org 70 i- r, _ := gzip.NewReader(b) Err parazyd.org 70 i- nodes := make(map[string]map[string]interface{}) Err parazyd.org 70 i- dec = json.NewDecoder(r) Err parazyd.org 70 i- if err = dec.Decode(&nodes); err != nil { Err parazyd.org 70 i- return false, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- for k, v := range nodes { Err parazyd.org 70 i- log.Printf("Adding %s to redis\n", k) Err parazyd.org 70 i- if _, err := rcli.HSet(rctx, k, v).Result(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return true, nil Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/api.go b/api.go /git/tordam/file/api.go.gph parazyd.org 70 it@@ -1,191 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "encoding/json" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "net/http" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func postback(rw http.ResponseWriter, data map[string]string, ret int) error { Err parazyd.org 70 i- val, err := json.Marshal(data) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- rw.Header().Set("Content-Type", "application/json") Err parazyd.org 70 i- rw.WriteHeader(ret) Err parazyd.org 70 i- if _, err := rw.Write(val); err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- return nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func handleAnnounce(rw http.ResponseWriter, req *http.Request) { Err parazyd.org 70 i- var r map[string]string Err parazyd.org 70 i- var n Node Err parazyd.org 70 i- Err parazyd.org 70 i- if req.Method != "POST" || req.Header["Content-Type"][0] != "application/json" { Err parazyd.org 70 i- r = map[string]string{"secret": "Invalid request format"} Err parazyd.org 70 i- if err := postback(rw, r, 400); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- dec := json.NewDecoder(req.Body) Err parazyd.org 70 i- if err := dec.Decode(&n); err != nil { Err parazyd.org 70 i- log.Println("Failed decoding request:", err) Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Bail out as soon as possible Err parazyd.org 70 i- if len(n.Address) == 0 || len(n.Message) == 0 || len(n.Signature) == 0 { Err parazyd.org 70 i- r = map[string]string{"secret": "Invalid request format"} Err parazyd.org 70 i- if err := postback(rw, r, 400); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if !validateOnionAddress(n.Address) { Err parazyd.org 70 i- log.Println("Invalid onion address:", n.Address) Err parazyd.org 70 i- r = map[string]string{"secret": "Invalid onion address"} Err parazyd.org 70 i- if err := postback(rw, r, 400); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- rq := map[string]string{ Err parazyd.org 70 i- "address": n.Address, Err parazyd.org 70 i- "message": n.Message, Err parazyd.org 70 i- "pubkey": n.Pubkey, Err parazyd.org 70 i- "signature": n.Signature, Err parazyd.org 70 i- "secret": n.Secret, Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // First handshake Err parazyd.org 70 i- if len(n.Message) != 88 || len(n.Secret) != 88 { Err parazyd.org 70 i- valid, msg := firstHandshake(rq) Err parazyd.org 70 i- r = map[string]string{"secret": msg} Err parazyd.org 70 i- if valid { Err parazyd.org 70 i- log.Printf("%s: 1/2 handskake valid\n", n.Address) Err parazyd.org 70 i- log.Println("Sending nonce to", n.Address) Err parazyd.org 70 i- if err := postback(rw, r, 200); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- log.Printf("%s: 1/2 handshake invalid: %s\n", n.Address, msg) Err parazyd.org 70 i- // Delete it all from redis Err parazyd.org 70 i- // TODO: Can this be abused? Err parazyd.org 70 i- if _, err := rcli.Del(rctx, n.Address).Result(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Second handshake Err parazyd.org 70 i- if len(rq["secret"]) == 88 && len(rq["message"]) == 88 { Err parazyd.org 70 i- valid, msg := secondHandshake(rq) Err parazyd.org 70 i- r = map[string]string{"secret": msg} Err parazyd.org 70 i- Err parazyd.org 70 i- if valid { Err parazyd.org 70 i- log.Printf("%s: 2/2 handshake valid\n", n.Address) Err parazyd.org 70 i- isTrusted, err := rcli.HGet(rctx, n.Address, "trusted").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Assume our name is what was requested Err parazyd.org 70 i- us := strings.TrimSuffix(req.Host, ":49371") Err parazyd.org 70 i- nodemap := make(map[string]map[string]string) Err parazyd.org 70 i- Err parazyd.org 70 i- if isTrusted == "1" { Err parazyd.org 70 i- // The node is marked as trusted so we'll teack it about other Err parazyd.org 70 i- // trusted nodes we know about. Err parazyd.org 70 i- log.Printf("%s is trusted. Propagating knowledge...\n", n.Address) Err parazyd.org 70 i- nodes, err := rcli.Keys(rctx, "*.onion").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- for _, i := range nodes { Err parazyd.org 70 i- if i == n.Address { Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- nodedata, err := rcli.HGetAll(rctx, i).Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if nodedata["trusted"] == "1" { Err parazyd.org 70 i- nodemap[i] = nodedata Err parazyd.org 70 i- delete(nodemap[i], "secret") Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- } else { Err parazyd.org 70 i- log.Printf("%s is not trusted. Propagating self...", n.Address) Err parazyd.org 70 i- // The node doesn't have trust in the network. We will only Err parazyd.org 70 i- // teach it about ourself. Err parazyd.org 70 i- nodedata, err := rcli.HGetAll(rctx, us).Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- nodemap[us] = nodedata Err parazyd.org 70 i- delete(nodemap[us], "secret") Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- nodestr, err := json.Marshal(nodemap) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- comp, err := gzipEncode(nodestr) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- r = map[string]string{"secret": comp} Err parazyd.org 70 i- if err := postback(rw, r, 200); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- publishToRedis('M', n.Address) Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // If we haven't returned so far, the handshake is invalid Err parazyd.org 70 i- log.Printf("%s: 2/2 handshake invalid\n", n.Address) Err parazyd.org 70 i- // Delete it all from redis Err parazyd.org 70 i- // TODO: Can this be abused? Err parazyd.org 70 i- publishToRedis('D', n.Address) Err parazyd.org 70 i- if _, err := rcli.Del(rctx, n.Address).Result(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if err := postback(rw, r, 400); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func handleElse(rw http.ResponseWriter, req *http.Request) { Err parazyd.org 70 i- log.Println("Got handleElse") Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/config.go b/config.go /git/tordam/file/config.go.gph parazyd.org 70 it@@ -1,36 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto/ed25519" Err parazyd.org 70 i- "net" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-const ( Err parazyd.org 70 i- seedName = "ed25519.seed" Err parazyd.org 70 i- pubsubChan = "tordam" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-var ( Err parazyd.org 70 i- redisAddr *net.TCPAddr Err parazyd.org 70 i- torAddr *net.TCPAddr Err parazyd.org 70 i- signingKey ed25519.PrivateKey Err parazyd.org 70 i-) Err parazyd.org 70 1diff --git a/contrib/tordam.png b/contrib/tordam.png /git/tordam/file/contrib/tordam.png.gph parazyd.org 70 iBinary files differ. Err parazyd.org 70 1diff --git a/crypto.go b/crypto.go /git/tordam/file/crypto.go.gph parazyd.org 70 it@@ -1,63 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto/ed25519" Err parazyd.org 70 i- "crypto/rand" Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func generateED25519Keypair(dir string) error { Err parazyd.org 70 i- _, sk, err := ed25519.GenerateKey(rand.Reader) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if err := os.MkdirAll(dir, 0700); err != nil { Err parazyd.org 70 i- return err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- seedpath := strings.Join([]string{dir, seedName}, "/") Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Writing ed25519 key seed to", seedpath) Err parazyd.org 70 i- return ioutil.WriteFile(seedpath, Err parazyd.org 70 i- []byte(base64.StdEncoding.EncodeToString(sk.Seed())), 0600) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func loadED25519Seed(file string) (ed25519.PrivateKey, error) { Err parazyd.org 70 i- log.Println("Reading ed25519 seed from", file) Err parazyd.org 70 i- Err parazyd.org 70 i- data, err := ioutil.ReadFile(file) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- dec, err := base64.StdEncoding.DecodeString(string(data)) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return ed25519.NewKeyFromSeed(dec), nil Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/helpers.go b/helpers.go /git/tordam/file/helpers.go.gph parazyd.org 70 it@@ -1,88 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "bytes" Err parazyd.org 70 i- "compress/gzip" Err parazyd.org 70 i- "crypto/rand" Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "fmt" Err parazyd.org 70 i- "math/big" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func genRandomASCII(length int) (string, error) { Err parazyd.org 70 i- var res string Err parazyd.org 70 i- for { Err parazyd.org 70 i- if len(res) == length { Err parazyd.org 70 i- return res, nil Err parazyd.org 70 i- } Err parazyd.org 70 i- num, err := rand.Int(rand.Reader, big.NewInt(int64(127))) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return "", err Err parazyd.org 70 i- } Err parazyd.org 70 i- n := num.Int64() Err parazyd.org 70 i- if n > 32 && n < 127 { Err parazyd.org 70 i- res += fmt.Sprint(n) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func gzipEncode(data []byte) (string, error) { Err parazyd.org 70 i- var b bytes.Buffer Err parazyd.org 70 i- gz := gzip.NewWriter(&b) Err parazyd.org 70 i- if _, err := gz.Write(data); err != nil { Err parazyd.org 70 i- return "", err Err parazyd.org 70 i- } Err parazyd.org 70 i- if err := gz.Flush(); err != nil { Err parazyd.org 70 i- return "", err Err parazyd.org 70 i- } Err parazyd.org 70 i- if err := gz.Close(); err != nil { Err parazyd.org 70 i- return "", err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return base64.StdEncoding.EncodeToString(b.Bytes()), nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func stringInSlice(str string, slice []string) bool { Err parazyd.org 70 i- for _, i := range slice { Err parazyd.org 70 i- if str == i { Err parazyd.org 70 i- return true Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- return false Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func parseDirs(sl []string, data []byte) []string { Err parazyd.org 70 i- dirstr := string(data) Err parazyd.org 70 i- _dirs := strings.Split(dirstr, "\n") Err parazyd.org 70 i- for _, i := range _dirs { Err parazyd.org 70 i- if strings.HasPrefix(i, "DIR:") { Err parazyd.org 70 i- t := strings.Split(i, "DIR:") Err parazyd.org 70 i- if !stringInSlice(t[1], sl) { Err parazyd.org 70 i- if validateOnionAddress(t[1]) { Err parazyd.org 70 i- sl = append(sl, t[1]) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- return sl Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/net.go b/net.go /git/tordam/file/net.go.gph parazyd.org 70 it@@ -1,83 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "bytes" Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "net" Err parazyd.org 70 i- "net/http" Err parazyd.org 70 i- Err parazyd.org 70 i- "golang.org/x/net/proxy" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func getListener() (*net.TCPAddr, error) { Err parazyd.org 70 i- addr, err := net.ResolveTCPAddr("tcp4", "localhost:0") Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- l, err := net.ListenTCP("tcp4", addr) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- defer l.Close() Err parazyd.org 70 i- return l.Addr().(*net.TCPAddr), nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func httpPost(host string, data []byte) (*http.Response, error) { Err parazyd.org 70 i- httpTransp := &http.Transport{} Err parazyd.org 70 i- httpClient := &http.Client{Transport: httpTransp} Err parazyd.org 70 i- dialer, err := proxy.SOCKS5("tcp", torAddr.String(), nil, proxy.Direct) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- httpTransp.Dial = dialer.Dial Err parazyd.org 70 i- Err parazyd.org 70 i- request, err := http.NewRequest("POST", host, bytes.NewBuffer(data)) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- request.Header.Set("Content-Type", "application/json") Err parazyd.org 70 i- return httpClient.Do(request) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func httpGet(uri string) ([]byte, error) { Err parazyd.org 70 i- httpTransp := &http.Transport{} Err parazyd.org 70 i- httpClient := &http.Client{Transport: httpTransp} Err parazyd.org 70 i- dialer, err := proxy.SOCKS5("tcp", torAddr.String(), nil, proxy.Direct) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- httpTransp.Dial = dialer.Dial Err parazyd.org 70 i- Err parazyd.org 70 i- request, err := http.NewRequest("GET", uri, nil) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- res, err := httpClient.Do(request) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- defer res.Body.Close() Err parazyd.org 70 i- return ioutil.ReadAll(res.Body) Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/redis.go b/redis.go /git/tordam/file/redis.go.gph parazyd.org 70 it@@ -1,141 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "context" Err parazyd.org 70 i- "fmt" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "os/exec" Err parazyd.org 70 i- "strconv" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i- "time" Err parazyd.org 70 i- Err parazyd.org 70 i- "github.com/go-redis/redis" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-// rctx is the Redis context (necessary in newer go-redis) Err parazyd.org 70 i-var rctx = context.Background() Err parazyd.org 70 i-var rcli *redis.Client Err parazyd.org 70 i- Err parazyd.org 70 i-func pollPrune(interval int64) { Err parazyd.org 70 i- for { Err parazyd.org 70 i- log.Println("Polling redis for expired nodes") Err parazyd.org 70 i- nodes, err := rcli.Keys(rctx, "*.onion").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Println("WARNING: Nonfatal error in pollPrune:", err.Error()) Err parazyd.org 70 i- } Err parazyd.org 70 i- now := time.Now().Unix() Err parazyd.org 70 i- Err parazyd.org 70 i- for _, i := range nodes { Err parazyd.org 70 i- res, err := rcli.HGet(rctx, i, "lastseen").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Println("WARNING: Nonfatal error in pollPrune:", err.Error()) Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- ls, err := strconv.Atoi(res) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Println("WARNING: Nonfatal error in pollPrune:", err.Error()) Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- diff := (now - int64(ls)) / 60 Err parazyd.org 70 i- if diff > interval { Err parazyd.org 70 i- log.Printf("Deleting %s (expired)\n", i) Err parazyd.org 70 i- publishToRedis('D', i) Err parazyd.org 70 i- rcli.Del(rctx, i) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- time.Sleep(time.Duration(interval) * time.Minute) Err parazyd.org 70 i- } Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func publishToRedis(mt rune, addr string) { Err parazyd.org 70 i- data, err := rcli.HGetAll(rctx, addr).Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Println("WARNING: Nonfatal err in publishToRedis:", err.Error()) Err parazyd.org 70 i- return Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if data["lastseen"] == data["firstseen"] { Err parazyd.org 70 i- mt = 'A' Err parazyd.org 70 i- } else if mt != 'D' { Err parazyd.org 70 i- mt = 'M' Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // TODO: First of the "addr" references could be alias/nickname Err parazyd.org 70 i- Err parazyd.org 70 i- rcli.Publish(rctx, pubsubChan, fmt.Sprintf("%s|%s|%v|%s", Err parazyd.org 70 i- data["lastseen"], addr, mt, addr)) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func newredisrc(dir string) string { Err parazyd.org 70 i- return fmt.Sprintf(`daemonize no Err parazyd.org 70 i-bind %s Err parazyd.org 70 i-port %d Err parazyd.org 70 i-databases 1 Err parazyd.org 70 i-dir %s Err parazyd.org 70 i-dbfilename tor-dam.rdb Err parazyd.org 70 i-save 900 1 Err parazyd.org 70 i-save 300 10 Err parazyd.org 70 i-save 60 10000 Err parazyd.org 70 i-rdbcompression yes Err parazyd.org 70 i-rdbchecksum yes Err parazyd.org 70 i-stop-writes-on-bgsave-error no`, Err parazyd.org 70 i- redisAddr.IP.String(), redisAddr.Port, dir) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func spawnRedis() (*exec.Cmd, error) { Err parazyd.org 70 i- var err error Err parazyd.org 70 i- redisAddr, err = getListener() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- rcli = redis.NewClient(&redis.Options{ Err parazyd.org 70 i- Addr: redisAddr.String(), Err parazyd.org 70 i- Password: "", Err parazyd.org 70 i- DB: 0, Err parazyd.org 70 i- }) Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Forking Redis daemon on", redisAddr.String()) Err parazyd.org 70 i- Err parazyd.org 70 i- cmd := exec.Command("redis-server", "-") Err parazyd.org 70 i- cmd.Stdin = strings.NewReader(newredisrc(*workdir)) Err parazyd.org 70 i- Err parazyd.org 70 i- err = cmd.Start() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- time.Sleep(500 * time.Millisecond) Err parazyd.org 70 i- if _, err := rcli.Ping(rctx).Result(); err != nil { Err parazyd.org 70 i- return cmd, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- pubsub := rcli.Subscribe(rctx, pubsubChan) Err parazyd.org 70 i- if _, err := pubsub.Receive(rctx); err != nil { Err parazyd.org 70 i- return cmd, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Printf("Created \"%s\" channel in Redis\n", pubsubChan) Err parazyd.org 70 i- Err parazyd.org 70 i- return cmd, nil Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/tor-dam.go b/tor-dam.go /git/tordam/file/tor-dam.go.gph parazyd.org 70 it@@ -1,191 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto/ed25519" Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "flag" Err parazyd.org 70 i- "fmt" Err parazyd.org 70 i- "io/ioutil" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "net" Err parazyd.org 70 i- "net/http" Err parazyd.org 70 i- "net/url" Err parazyd.org 70 i- "os" Err parazyd.org 70 i- "strconv" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i- "sync" Err parazyd.org 70 i- "time" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-var ( Err parazyd.org 70 i- noremote = flag.Bool("n", false, "Don't fetch remote entrypoints") Err parazyd.org 70 i- generate = flag.Bool("g", false, "(Re)generate keys and exit") Err parazyd.org 70 i- annint = flag.Int("i", 5, "Announce interval (in minutes)") Err parazyd.org 70 i- remote = flag.String("r", "https://parazyd.org/pub/tmp/tor-dam-dirs.txt", Err parazyd.org 70 i- "Remote list of entrypoints (comma-separated)") Err parazyd.org 70 i- portmap = flag.String("p", "13010:13010,13011:13011,5000:5000", Err parazyd.org 70 i- "Map of ports forwarded to/from Tor") Err parazyd.org 70 i- expiry = flag.Int64("e", 0, "Node expiry time in minutes (0=unlimited)") Err parazyd.org 70 i- trustall = flag.Bool("t", false, "Trust all new nodes automatically") Err parazyd.org 70 i- listen = "127.0.0.1:49371" Err parazyd.org 70 i- //listen = flag.String("l", "127.0.0.1:49371", Err parazyd.org 70 i- //"Listen address for daemon (Will also map in Tor HS)") Err parazyd.org 70 i- workdir = flag.String("d", os.Getenv("HOME")+"/.dam", "Working directory") Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func flagSanity() error { Err parazyd.org 70 i- for _, i := range strings.Split(*remote, ",") { Err parazyd.org 70 i- if _, err := url.ParseRequestURI(i); err != nil { Err parazyd.org 70 i- return fmt.Errorf("invalid URL \"%s\" in remote entrypoints", i) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- for _, i := range strings.Split(*portmap, ",") { Err parazyd.org 70 i- t := strings.Split(i, ":") Err parazyd.org 70 i- if len(t) != 2 { Err parazyd.org 70 i- return fmt.Errorf("invalid portmap: %s (len != 2)", i) Err parazyd.org 70 i- } Err parazyd.org 70 i- if _, err := strconv.Atoi(t[0]); err != nil { Err parazyd.org 70 i- return fmt.Errorf("invalid portmap: %s (%s)", i, err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if _, err := strconv.Atoi(t[1]); err != nil { Err parazyd.org 70 i- return fmt.Errorf("invalid portmap: %s (%s)", i, err) Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if _, err := net.ResolveTCPAddr("tcp", listen); err != nil { Err parazyd.org 70 i- return fmt.Errorf("invalid listen address: %s (%s)", listen, err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return nil Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func main() { Err parazyd.org 70 i- flag.Parse() Err parazyd.org 70 i- var wg sync.WaitGroup Err parazyd.org 70 i- var err error Err parazyd.org 70 i- Err parazyd.org 70 i- if err := flagSanity(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if *generate { Err parazyd.org 70 i- if err := generateED25519Keypair(*workdir); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- os.Exit(0) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- signingKey, err = loadED25519Seed(strings.Join( Err parazyd.org 70 i- []string{*workdir, seedName}, "/")) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- tor, err := spawnTor() Err parazyd.org 70 i- defer tor.Process.Kill() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- red, err := spawnRedis() Err parazyd.org 70 i- defer red.Process.Kill() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- mux := http.NewServeMux() Err parazyd.org 70 i- mux.HandleFunc("/announce", handleAnnounce) Err parazyd.org 70 i- mux.HandleFunc("/", handleElse) Err parazyd.org 70 i- srv := &http.Server{ Err parazyd.org 70 i- Addr: listen, Err parazyd.org 70 i- Handler: mux, Err parazyd.org 70 i- ReadTimeout: 30 * time.Second, Err parazyd.org 70 i- WriteTimeout: 30 * time.Second, Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- go srv.ListenAndServe() Err parazyd.org 70 i- log.Println("tor-dam directory listening on", listen) Err parazyd.org 70 i- Err parazyd.org 70 i- if *trustall { Err parazyd.org 70 i- log.Println("Trustall enabled, will mark all nodes trusted by default") Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if *expiry > 0 { Err parazyd.org 70 i- log.Printf("Enabling db prune polling (%d minute interval)\n", *expiry) Err parazyd.org 70 i- go pollPrune(*expiry) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- onionaddr, err := ioutil.ReadFile(strings.Join([]string{ Err parazyd.org 70 i- *workdir, "hs", "hostname"}, "/")) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- onionaddr = []byte(strings.TrimSuffix(string(onionaddr), "\n")) Err parazyd.org 70 i- log.Printf("Our hostname is: %s\n", string(onionaddr)) Err parazyd.org 70 i- Err parazyd.org 70 i- // Network entrypoints. These files hold the lists of nodes we can announce Err parazyd.org 70 i- // to initially. Format is "DIR:unlikelynameforan.onion", other lines are Err parazyd.org 70 i- // ignored and can be used as comments or siimilar. Err parazyd.org 70 i- epLists := strings.Split(*remote, ",") Err parazyd.org 70 i- Err parazyd.org 70 i- for { Err parazyd.org 70 i- log.Println("Announcing to nodes...") Err parazyd.org 70 i- var ann = 0 // Track of successful authentications Err parazyd.org 70 i- nodes, err := fetchNodeList(epLists, *noremote) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- // No route to host, or failed download. Try later. Err parazyd.org 70 i- log.Printf("Failed to fetch nodes, retrying in 1m (%s)\n", err) Err parazyd.org 70 i- time.Sleep(60 * time.Second) Err parazyd.org 70 i- continue Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- sigmsg := []byte("Hi tor-dam!") Err parazyd.org 70 i- Err parazyd.org 70 i- nv := map[string]string{ Err parazyd.org 70 i- "address": string(onionaddr), Err parazyd.org 70 i- "pubkey": base64.StdEncoding.EncodeToString(signingKey.Public().(ed25519.PublicKey)), Err parazyd.org 70 i- "message": string(sigmsg), Err parazyd.org 70 i- "signature": base64.StdEncoding.EncodeToString(ed25519.Sign(signingKey, sigmsg)), Err parazyd.org 70 i- "secret": "", Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- for _, i := range nodes { Err parazyd.org 70 i- wg.Add(1) Err parazyd.org 70 i- go func(x string) { Err parazyd.org 70 i- valid, err := announce(x, nv) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Printf("%s: %s\n", x, err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if valid { Err parazyd.org 70 i- ann++ Err parazyd.org 70 i- } Err parazyd.org 70 i- wg.Done() Err parazyd.org 70 i- }(i) Err parazyd.org 70 i- } Err parazyd.org 70 i- wg.Wait() Err parazyd.org 70 i- Err parazyd.org 70 i- log.Printf("%d successful authentications\n", ann) Err parazyd.org 70 i- log.Printf("Waiting %d min before next announce\n", *annint) Err parazyd.org 70 i- time.Sleep(time.Duration(*annint) * time.Minute) Err parazyd.org 70 i- } Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/tor.go b/tor.go /git/tordam/file/tor.go.gph parazyd.org 70 it@@ -1,68 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "fmt" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "os/exec" Err parazyd.org 70 i- "strings" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func newtorrc(dir string) string { Err parazyd.org 70 i- var pm []string Err parazyd.org 70 i- Err parazyd.org 70 i- for _, i := range strings.Split(*portmap, ",") { Err parazyd.org 70 i- p := strings.Split(i, ":") Err parazyd.org 70 i- pm = append(pm, fmt.Sprintf("HiddenServicePort %s %s", Err parazyd.org 70 i- p[0], strings.Join([]string{"127.0.0.1", p[1]}, ":"))) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return fmt.Sprintf(`Log warn syslog Err parazyd.org 70 i-RunAsDaemon 0 Err parazyd.org 70 i-DataDirectory %s/tor Err parazyd.org 70 i-SocksPort %s Err parazyd.org 70 i-HiddenServiceDir %s/hs Err parazyd.org 70 i-HiddenServicePort %s %s Err parazyd.org 70 i-%s Err parazyd.org 70 i-`, Err parazyd.org 70 i- dir, torAddr.String(), dir, strings.Split(listen, ":")[1], Err parazyd.org 70 i- listen, strings.Join(pm, "\n")) Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func spawnTor() (*exec.Cmd, error) { Err parazyd.org 70 i- var err error Err parazyd.org 70 i- torAddr, err = getListener() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Println("Forking Tor daemon on", torAddr.String()) Err parazyd.org 70 i- Err parazyd.org 70 i- cmd := exec.Command("tor", "-f", "-") Err parazyd.org 70 i- cmd.Stdin = strings.NewReader(newtorrc(*workdir)) Err parazyd.org 70 i- Err parazyd.org 70 i- err = cmd.Start() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- return nil, err Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return cmd, nil Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/types.go b/types.go /git/tordam/file/types.go.gph parazyd.org 70 it@@ -1,37 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-// Message represents the message struct type Err parazyd.org 70 i-type Message struct { Err parazyd.org 70 i- Secret string `json:"secret"` Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// Node represents the node struct type Err parazyd.org 70 i-type Node struct { Err parazyd.org 70 i- Address string `json:"address"` Err parazyd.org 70 i- Message string `json:"message"` Err parazyd.org 70 i- Signature string `json:"signature"` Err parazyd.org 70 i- Secret string `json:"secret"` Err parazyd.org 70 i- Pubkey string `json:"pubkey"` Err parazyd.org 70 i- Firstseen int64 `json:"firstseen"` Err parazyd.org 70 i- Lastseen int64 `json:"lastseen"` Err parazyd.org 70 i- Trusted int `json:"trusted"` Err parazyd.org 70 i-} Err parazyd.org 70 1diff --git a/validate.go b/validate.go /git/tordam/file/validate.go.gph parazyd.org 70 it@@ -1,158 +0,0 @@ Err parazyd.org 70 i-package main Err parazyd.org 70 i- Err parazyd.org 70 i-/* Err parazyd.org 70 i- * Copyright (c) 2017-2021 Ivan Jelincic Err parazyd.org 70 i- * Err parazyd.org 70 i- * This file is part of tor-dam Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is free software: you can redistribute it and/or modify Err parazyd.org 70 i- * it under the terms of the GNU Affero General Public License as published by Err parazyd.org 70 i- * the Free Software Foundation, either version 3 of the License, or Err parazyd.org 70 i- * (at your option) any later version. Err parazyd.org 70 i- * Err parazyd.org 70 i- * This program is distributed in the hope that it will be useful, Err parazyd.org 70 i- * but WITHOUT ANY WARRANTY; without even the implied warranty of Err parazyd.org 70 i- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Err parazyd.org 70 i- * GNU Affero General Public License for more details. Err parazyd.org 70 i- * Err parazyd.org 70 i- * You should have received a copy of the GNU Affero General Public License Err parazyd.org 70 i- * along with this program. If not, see . Err parazyd.org 70 i- */ Err parazyd.org 70 i- Err parazyd.org 70 i-import ( Err parazyd.org 70 i- "crypto/ed25519" Err parazyd.org 70 i- "encoding/base64" Err parazyd.org 70 i- "log" Err parazyd.org 70 i- "regexp" Err parazyd.org 70 i- "time" Err parazyd.org 70 i-) Err parazyd.org 70 i- Err parazyd.org 70 i-func validateOnionAddress(addr string) bool { Err parazyd.org 70 i- re, _ := regexp.Compile(`^[a-z2-7](?:.{55})\.onion`) Err parazyd.org 70 i- return len(re.FindString(addr)) == 62 Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-// firstHandshake will take the incoming public key either from the request Err parazyd.org 70 i-// or, if found, from redis. This key is stored, and a nonce is generated. Err parazyd.org 70 i-// This nonce is returned back to the client to sign with the key. In the Err parazyd.org 70 i-// second handshake, we verify this nonce signature against the retrieved Err parazyd.org 70 i-// public key. Err parazyd.org 70 i-func firstHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i- var pubstr string Err parazyd.org 70 i- Err parazyd.org 70 i- // Check if we have seen this node already Err parazyd.org 70 i- ex, err := rcli.Exists(rctx, req["address"]).Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if ex == 1 { Err parazyd.org 70 i- // We saw it so we should hae the public key stored in redis. Err parazyd.org 70 i- // If we do not, that is an internal error. Err parazyd.org 70 i- pubstr, err = rcli.HGet(rctx, req["address"], "pubkey").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- } else { Err parazyd.org 70 i- // We take it from the request Err parazyd.org 70 i- pubstr = req["pubkey"] Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- randString, err := genRandomASCII(64) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- enc := base64.StdEncoding.EncodeToString([]byte(randString)) Err parazyd.org 70 i- Err parazyd.org 70 i- var info = map[string]interface{}{ Err parazyd.org 70 i- "address": req["address"], Err parazyd.org 70 i- "message": enc, Err parazyd.org 70 i- "signature": req["signature"], Err parazyd.org 70 i- "secret": enc, Err parazyd.org 70 i- "lastseen": time.Now().Unix(), Err parazyd.org 70 i- } // Can not cast, need this for HSet Err parazyd.org 70 i- Err parazyd.org 70 i- if ex != 1 { Err parazyd.org 70 i- // We did not have this node in redis Err parazyd.org 70 i- info["pubkey"] = pubstr Err parazyd.org 70 i- info["firstseen"] = time.Now().Unix() Err parazyd.org 70 i- if *trustall { Err parazyd.org 70 i- info["trusted"] = 1 Err parazyd.org 70 i- } else { Err parazyd.org 70 i- info["trusted"] = 0 Err parazyd.org 70 i- } Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- log.Printf("%s: Writing to redis\n", req["address"]) Err parazyd.org 70 i- if _, err := rcli.HSet(rctx, req["address"], info).Result(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return true, enc Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-func secondHandshake(req map[string]string) (bool, string) { Err parazyd.org 70 i- // Check if we have seen this node already Err parazyd.org 70 i- ex, err := rcli.Exists(rctx, req["address"]).Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- if ex != 1 { Err parazyd.org 70 i- log.Printf("%s tried to jump in 2/2 handshake before getting a nonce\n", Err parazyd.org 70 i- req["address"]) Err parazyd.org 70 i- return false, "We have not seen you before. Authenticate properly." Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // We saw it so we should have the public key in redis. If we do not, Err parazyd.org 70 i- // then it's an internal error. Err parazyd.org 70 i- pubstr, err := rcli.HGet(rctx, req["address"], "pubkey").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- lSec, err := rcli.HGet(rctx, req["address"], "secret").Result() Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- if lSec != req["secret"] || lSec != req["message"] { Err parazyd.org 70 i- log.Printf("%s: Secrets didn't match\n", req["address"]) Err parazyd.org 70 i- return false, "Secrets didn't match." Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // Validate signature. Err parazyd.org 70 i- msg := []byte(lSec) Err parazyd.org 70 i- sig, _ := base64.StdEncoding.DecodeString(req["signature"]) Err parazyd.org 70 i- deckey, err := base64.StdEncoding.DecodeString(pubstr) Err parazyd.org 70 i- if err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- pubkey := ed25519.PublicKey(deckey) Err parazyd.org 70 i- Err parazyd.org 70 i- if !ed25519.Verify(pubkey, msg, sig) { Err parazyd.org 70 i- log.Println("crypto/ed25519: Signature verification failure") Err parazyd.org 70 i- return false, "Signature verification failure" Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- // The request is valid at this point Err parazyd.org 70 i- Err parazyd.org 70 i- // Make a new random secret to prevent reuse. Err parazyd.org 70 i- randString, _ := genRandomASCII(64) Err parazyd.org 70 i- encSecret := base64.StdEncoding.EncodeToString([]byte(randString)) Err parazyd.org 70 i- Err parazyd.org 70 i- var info = map[string]interface{}{ Err parazyd.org 70 i- "address": req["address"], Err parazyd.org 70 i- "message": encSecret, Err parazyd.org 70 i- "signature": req["signature"], Err parazyd.org 70 i- "secret": encSecret, Err parazyd.org 70 i- "lastseen": time.Now().Unix(), Err parazyd.org 70 i- } // TODO: Use struct Err parazyd.org 70 i- Err parazyd.org 70 i- log.Printf("Adding %s to redis\n", req["address"]) Err parazyd.org 70 i- if _, err := rcli.HSet(rctx, req["address"], info).Result(); err != nil { Err parazyd.org 70 i- log.Fatal(err) Err parazyd.org 70 i- } Err parazyd.org 70 i- Err parazyd.org 70 i- return true, "Welcome to tor-dam" Err parazyd.org 70 i-} Err parazyd.org 70 .