tpeer_announce.go - tordam - A library for peer discovery inside the Tor network
 (HTM) git clone https://git.parazyd.org/tordam
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tpeer_announce.go (3265B)
       ---
            1 // Copyright (c) 2017-2021 Ivan Jelincic <parazyd@dyne.org>
            2 //
            3 // This file is part of tordam
            4 //
            5 // This program is free software: you can redistribute it and/or modify
            6 // it under the terms of the GNU Affero General Public License as published by
            7 // the Free Software Foundation, either version 3 of the License, or
            8 // (at your option) any later version.
            9 //
           10 // This program is distributed in the hope that it will be useful,
           11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
           12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
           13 // GNU Affero General Public License for more details.
           14 //
           15 // You should have received a copy of the GNU Affero General Public License
           16 // along with this program. If not, see <https://www.gnu.org/licenses/>.
           17 
           18 package tordam
           19 
           20 import (
           21         "context"
           22         "crypto/ed25519"
           23         "encoding/base64"
           24         "fmt"
           25         "strings"
           26 
           27         "github.com/creachadair/jrpc2"
           28         "github.com/creachadair/jrpc2/channel"
           29         "golang.org/x/net/proxy"
           30 )
           31 
           32 // Announce is a function that announces to a certain onion address. Upon
           33 // success, it appends the peers received from the endpoint to the global
           34 // Peers map, which in turn also writes it to the peers db file.
           35 func Announce(onionaddr string) error {
           36         rpcInfo(fmt.Sprintf("Announcing to %s", onionaddr))
           37 
           38         if err := ValidateOnionInternal(onionaddr); err != nil {
           39                 return err
           40         }
           41 
           42         socks, err := proxy.SOCKS5("tcp", Cfg.TorAddr.String(), nil, proxy.Direct)
           43         if err != nil {
           44                 return err
           45         }
           46 
           47         // conn, err := net.Dial(jrpc2.Network(Cfg.Listen), Cfg.Listen)
           48         conn, err := socks.Dial("tcp", onionaddr)
           49         if err != nil {
           50                 return err
           51         }
           52         defer conn.Close()
           53 
           54         cli := jrpc2.NewClient(channel.RawJSON(conn, conn), nil)
           55         defer cli.Close()
           56         ctx := context.Background()
           57 
           58         b64pk := base64.StdEncoding.EncodeToString(
           59                 SignKey.Public().(ed25519.PublicKey))
           60 
           61         var resp [2]string
           62         data := []string{Onion, b64pk, strings.Join(Cfg.Portmap, ",")}
           63 
           64         if peer, ok := Peers[onionaddr]; ok {
           65                 // Here the implication is that it's not our first announce, so we
           66                 // should have received a revoke key to use for a subsequent announce.
           67                 data = append(data, peer.SelfRevoke)
           68         }
           69 
           70         if err := cli.CallResult(ctx, "ann.Init", data, &resp); err != nil {
           71                 return err
           72         }
           73         nonce := resp[0]
           74 
           75         // TODO: Think about this >
           76         var peer Peer
           77         if _, ok := Peers[onionaddr]; ok {
           78                 peer = Peers[onionaddr]
           79         }
           80         peer.SelfRevoke = resp[1]
           81         Peers[onionaddr] = peer
           82 
           83         sig := base64.StdEncoding.EncodeToString(
           84                 ed25519.Sign(SignKey, []byte(nonce)))
           85 
           86         var newPeers []string
           87         if err := cli.CallResult(ctx, "ann.Validate",
           88                 []string{Onion, sig}, &newPeers); err != nil {
           89                 return err
           90         }
           91 
           92         return AppendPeers(newPeers)
           93 }
           94 
           95 // AppendPeers appends given []string peers to the global Peers map. Usually
           96 // received by validating ourself to a peer and them replying with a list of
           97 // their valid peers. If a peer is not in format of "unlikelyname.onion:port",
           98 // they will not be appended.
           99 // As a placeholder, this function can return an error, but it has no reason
          100 // to do so right now.
          101 func AppendPeers(p []string) error {
          102         for _, i := range p {
          103                 if _, ok := Peers[i]; ok {
          104                         continue
          105                 }
          106                 if err := ValidateOnionInternal(i); err != nil {
          107                         rpcWarn(fmt.Sprintf("received garbage peer (%v)", err))
          108                         continue
          109                 }
          110                 Peers[i] = Peer{}
          111         }
          112 
          113         return nil
          114 }