api.go (5014B)
1 package main 2 3 /* 4 * Copyright (c) 2017-2021 Ivan Jelincic <parazyd@dyne.org> 5 * 6 * This file is part of tor-dam 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 import ( 23 "encoding/json" 24 "log" 25 "net/http" 26 "strings" 27 ) 28 29 func postback(rw http.ResponseWriter, data map[string]string, ret int) error { 30 val, err := json.Marshal(data) 31 if err != nil { 32 return err 33 } 34 35 rw.Header().Set("Content-Type", "application/json") 36 rw.WriteHeader(ret) 37 if _, err := rw.Write(val); err != nil { 38 return err 39 } 40 return nil 41 } 42 43 func handleAnnounce(rw http.ResponseWriter, req *http.Request) { 44 var r map[string]string 45 var n Node 46 47 if req.Method != "POST" || req.Header["Content-Type"][0] != "application/json" { 48 r = map[string]string{"secret": "Invalid request format"} 49 if err := postback(rw, r, 400); err != nil { 50 log.Fatal(err) 51 } 52 return 53 } 54 55 dec := json.NewDecoder(req.Body) 56 if err := dec.Decode(&n); err != nil { 57 log.Println("Failed decoding request:", err) 58 return 59 } 60 61 // Bail out as soon as possible 62 if len(n.Address) == 0 || len(n.Message) == 0 || len(n.Signature) == 0 { 63 r = map[string]string{"secret": "Invalid request format"} 64 if err := postback(rw, r, 400); err != nil { 65 log.Fatal(err) 66 } 67 return 68 } 69 70 if !validateOnionAddress(n.Address) { 71 log.Println("Invalid onion address:", n.Address) 72 r = map[string]string{"secret": "Invalid onion address"} 73 if err := postback(rw, r, 400); err != nil { 74 log.Fatal(err) 75 } 76 return 77 } 78 79 rq := map[string]string{ 80 "address": n.Address, 81 "message": n.Message, 82 "pubkey": n.Pubkey, 83 "signature": n.Signature, 84 "secret": n.Secret, 85 } 86 87 // First handshake 88 if len(n.Message) != 88 || len(n.Secret) != 88 { 89 valid, msg := firstHandshake(rq) 90 r = map[string]string{"secret": msg} 91 if valid { 92 log.Printf("%s: 1/2 handskake valid\n", n.Address) 93 log.Println("Sending nonce to", n.Address) 94 if err := postback(rw, r, 200); err != nil { 95 log.Fatal(err) 96 } 97 return 98 } 99 log.Printf("%s: 1/2 handshake invalid: %s\n", n.Address, msg) 100 // Delete it all from redis 101 // TODO: Can this be abused? 102 if _, err := rcli.Del(rctx, n.Address).Result(); err != nil { 103 log.Fatal(err) 104 } 105 return 106 } 107 108 // Second handshake 109 if len(rq["secret"]) == 88 && len(rq["message"]) == 88 { 110 valid, msg := secondHandshake(rq) 111 r = map[string]string{"secret": msg} 112 113 if valid { 114 log.Printf("%s: 2/2 handshake valid\n", n.Address) 115 isTrusted, err := rcli.HGet(rctx, n.Address, "trusted").Result() 116 if err != nil { 117 log.Fatal(err) 118 } 119 120 // Assume our name is what was requested 121 us := strings.TrimSuffix(req.Host, ":49371") 122 nodemap := make(map[string]map[string]string) 123 124 if isTrusted == "1" { 125 // The node is marked as trusted so we'll teack it about other 126 // trusted nodes we know about. 127 log.Printf("%s is trusted. Propagating knowledge...\n", n.Address) 128 nodes, err := rcli.Keys(rctx, "*.onion").Result() 129 if err != nil { 130 log.Fatal(err) 131 } 132 for _, i := range nodes { 133 if i == n.Address { 134 continue 135 } 136 nodedata, err := rcli.HGetAll(rctx, i).Result() 137 if err != nil { 138 log.Fatal(err) 139 } 140 if nodedata["trusted"] == "1" { 141 nodemap[i] = nodedata 142 delete(nodemap[i], "secret") 143 } 144 } 145 } else { 146 log.Printf("%s is not trusted. Propagating self...", n.Address) 147 // The node doesn't have trust in the network. We will only 148 // teach it about ourself. 149 nodedata, err := rcli.HGetAll(rctx, us).Result() 150 if err != nil { 151 log.Fatal(err) 152 } 153 nodemap[us] = nodedata 154 delete(nodemap[us], "secret") 155 } 156 157 nodestr, err := json.Marshal(nodemap) 158 if err != nil { 159 log.Fatal(err) 160 } 161 comp, err := gzipEncode(nodestr) 162 if err != nil { 163 log.Fatal(err) 164 } 165 r = map[string]string{"secret": comp} 166 if err := postback(rw, r, 200); err != nil { 167 log.Fatal(err) 168 } 169 170 publishToRedis('M', n.Address) 171 return 172 } 173 174 // If we haven't returned so far, the handshake is invalid 175 log.Printf("%s: 2/2 handshake invalid\n", n.Address) 176 // Delete it all from redis 177 // TODO: Can this be abused? 178 publishToRedis('D', n.Address) 179 if _, err := rcli.Del(rctx, n.Address).Result(); err != nil { 180 log.Fatal(err) 181 } 182 if err := postback(rw, r, 400); err != nil { 183 log.Fatal(err) 184 } 185 return 186 } 187 } 188 189 func handleElse(rw http.ResponseWriter, req *http.Request) { 190 log.Println("Got handleElse") 191 }