diff options
author | Bernd Fix <brf@hoi-polloi.org> | 2022-08-21 16:40:12 +0200 |
---|---|---|
committer | Bernd Fix <brf@hoi-polloi.org> | 2022-08-21 16:40:12 +0200 |
commit | 21d7292dbd062ff11194fdc235a3d54830d7ba57 (patch) | |
tree | 75b5b1c620f4ac9cb722330c6bd9cbcdb24c7700 /src/gnunet/service/dht/path | |
parent | 5b03f7567ad8242cc87924c3920dfc04420365ef (diff) | |
download | gnunet-go-21d7292dbd062ff11194fdc235a3d54830d7ba57.tar.gz gnunet-go-21d7292dbd062ff11194fdc235a3d54830d7ba57.zip |
Integration test: bug fixes 1st round.
Diffstat (limited to 'src/gnunet/service/dht/path')
-rw-r--r-- | src/gnunet/service/dht/path/elements.go | 38 | ||||
-rw-r--r-- | src/gnunet/service/dht/path/elements_test.go | 71 | ||||
-rw-r--r-- | src/gnunet/service/dht/path/handling.go | 146 |
3 files changed, 164 insertions, 91 deletions
diff --git a/src/gnunet/service/dht/path/elements.go b/src/gnunet/service/dht/path/elements.go index 1384469..4fb03c1 100644 --- a/src/gnunet/service/dht/path/elements.go +++ b/src/gnunet/service/dht/path/elements.go | |||
@@ -36,6 +36,7 @@ var ( | |||
36 | ) | 36 | ) |
37 | 37 | ||
38 | //---------------------------------------------------------------------- | 38 | //---------------------------------------------------------------------- |
39 | |||
39 | // Entry is an element of the path list | 40 | // Entry is an element of the path list |
40 | type Entry struct { | 41 | type Entry struct { |
41 | Signature *util.PeerSignature // path element signature | 42 | Signature *util.PeerSignature // path element signature |
@@ -57,9 +58,9 @@ func (e *Entry) String() string { | |||
57 | return fmt.Sprintf("(%s,%s)", e.Signer.String(), s) | 58 | return fmt.Sprintf("(%s,%s)", e.Signer.String(), s) |
58 | } | 59 | } |
59 | 60 | ||
60 | //---------------------------------------------------------------------- | 61 | // ---------------------------------------------------------------------- |
61 | // shared path element data across types | 62 | // shared path element data across types |
62 | type elementData struct { | 63 | type _ElementData struct { |
63 | Expire util.AbsoluteTime // expiration date | 64 | Expire util.AbsoluteTime // expiration date |
64 | BlockHash *crypto.HashCode // block hash | 65 | BlockHash *crypto.HashCode // block hash |
65 | PeerPredecessor *util.PeerID // predecessor peer | 66 | PeerPredecessor *util.PeerID // predecessor peer |
@@ -67,41 +68,48 @@ type elementData struct { | |||
67 | } | 68 | } |
68 | 69 | ||
69 | // helper type for signature creation/verification | 70 | // helper type for signature creation/verification |
70 | type elementSignedData struct { | 71 | type _SignedData struct { |
71 | Size uint16 `order:"big"` // size of signed data | 72 | Purpose *crypto.SignaturePurpose // signature purpose |
72 | Purpose uint16 `order:"big"` // signature purpose (SIG_DHT_HOP) | 73 | Elem *_ElementData // path element data |
73 | Elem *elementData `` // path element data | ||
74 | } | 74 | } |
75 | 75 | ||
76 | //---------------------------------------------------------------------- | 76 | // ---------------------------------------------------------------------- |
77 | // Element is the full-fledged data assembly for a path element in | 77 | // Element is the full-fledged data assembly for a path element in |
78 | // PUT/GET pathes. It is assembled programatically (on generation[1] and | 78 | // PUT/GET pathes. It is assembled programatically (on generation[1] and |
79 | // verification[2]) and not transferred in messages directly. | 79 | // verification[2]) and not transferred in messages directly. |
80 | // | 80 | // |
81 | // [1] spe = &Element{...} | 81 | // [1] spe = &Element{...} |
82 | // core.Sign(spe) | 82 | // |
83 | // msg.putpath[i] = spe.Wire() | 83 | // core.Sign(spe) |
84 | // msg.putpath[i] = spe.Wire() | ||
84 | // | 85 | // |
85 | // [2] pe = &Element{...,Signature: wire.sig} | 86 | // [2] pe = &Element{...,Signature: wire.sig} |
86 | // if !pe.Verify(peerId) { ... } | ||
87 | // | 87 | // |
88 | // if !pe.Verify(peerId) { ... } | ||
88 | type Element struct { | 89 | type Element struct { |
89 | elementData | 90 | _ElementData |
90 | Entry | 91 | Entry |
91 | } | 92 | } |
92 | 93 | ||
93 | // SignedData gets the data to be signed by peer ('Signable' interface) | 94 | // SignedData gets the data to be signed by peer ('Signable' interface) |
94 | func (pe *Element) SignedData() []byte { | 95 | func (pe *Element) SignedData() []byte { |
95 | sd := &elementSignedData{ | 96 | sd := &_SignedData{ |
96 | Size: 80, | 97 | Purpose: &crypto.SignaturePurpose{ |
97 | Purpose: uint16(enums.SIG_DHT_HOP), | 98 | Size: 144, |
98 | Elem: &(pe.elementData), | 99 | Purpose: enums.SIG_DHT_HOP, |
100 | }, | ||
101 | Elem: &(pe._ElementData), | ||
99 | } | 102 | } |
100 | buf, err := data.Marshal(sd) | 103 | buf, err := data.Marshal(sd) |
101 | if err != nil { | 104 | if err != nil { |
102 | logger.Println(logger.ERROR, "can't serialize path element for signature") | 105 | logger.Println(logger.ERROR, "can't serialize path element for signature") |
103 | return nil | 106 | return nil |
104 | } | 107 | } |
108 | if len(buf) != int(sd.Purpose.Size) { | ||
109 | logger.Printf(logger.ERROR, "size mismatch for serialized path element -- %d -> %d", sd.Purpose.Size, len(buf)) | ||
110 | sd.Purpose.Size = uint32(len(buf)) | ||
111 | return nil | ||
112 | } | ||
105 | return buf | 113 | return buf |
106 | } | 114 | } |
107 | 115 | ||
diff --git a/src/gnunet/service/dht/path/elements_test.go b/src/gnunet/service/dht/path/elements_test.go new file mode 100644 index 0000000..68c2384 --- /dev/null +++ b/src/gnunet/service/dht/path/elements_test.go | |||
@@ -0,0 +1,71 @@ | |||
1 | // This file is part of gnunet-go, a GNUnet-implementation in Golang. | ||
2 | // Copyright (C) 2019-2022 Bernd Fix >Y< | ||
3 | // | ||
4 | // gnunet-go is free software: you can redistribute it and/or modify it | ||
5 | // under the terms of the GNU Affero General Public License as published | ||
6 | // by the Free Software Foundation, either version 3 of the License, | ||
7 | // or (at your option) any later version. | ||
8 | // | ||
9 | // gnunet-go is distributed in the hope that it will be useful, but | ||
10 | // WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | // Affero General Public License for more details. | ||
13 | // | ||
14 | // You should have received a copy of the GNU Affero General Public License | ||
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | // | ||
17 | // SPDX-License-Identifier: AGPL3.0-or-later | ||
18 | |||
19 | package path | ||
20 | |||
21 | import ( | ||
22 | "encoding/hex" | ||
23 | "gnunet/util" | ||
24 | "testing" | ||
25 | ) | ||
26 | |||
27 | func TestElementDebug(t *testing.T) { | ||
28 | var ( | ||
29 | signedData = "" + | ||
30 | "00000090" + | ||
31 | "00000006" + | ||
32 | "0005e6983d33f911" + | ||
33 | "f3236acc2be7812a988617c647fc27fcfbd0dacc3d960aa29a5f9bf0b9b9131f" + | ||
34 | "cdd31cfa45de2cbd9510665e7f2b1ccafefd445511c62729c0798dd1b0675f19" + | ||
35 | "0000000000000000000000000000000000000000000000000000000000000000" + | ||
36 | "23b096021b25d822c217a756b877cf72c7fdabd4eff79c4dbb7418dd2b232386" | ||
37 | |||
38 | signature = "" + | ||
39 | "ef94ddfd90b56f30b265a88384551907fadef176b4ba6b023df429506b34cde0" + | ||
40 | "39f38661d451e6e5bd1c4d5d078d27f0e8954bd964ea55f03afa42aa9964cc0c" | ||
41 | signer = "" + | ||
42 | "28f06fe5178742c3b8f080431e48cf5bf3898ba8b8fd57a975772d14003a8c75" | ||
43 | predecessor = "" + | ||
44 | "0000000000000000000000000000000000000000000000000000000000000000" | ||
45 | successor = "" + | ||
46 | "23b096021b25d822c217a756b877cf72c7fdabd4eff79c4dbb7418dd2b232386" | ||
47 | ) | ||
48 | convert := func(s string) []byte { | ||
49 | buf, err := hex.DecodeString(s) | ||
50 | if err != nil { | ||
51 | t.Fatal(err) | ||
52 | } | ||
53 | return buf | ||
54 | } | ||
55 | sd := convert(signedData) | ||
56 | sig := util.NewPeerSignature(convert(signature)) | ||
57 | pred := util.NewPeerID(convert(predecessor)) | ||
58 | curr := util.NewPeerID(convert(signer)) | ||
59 | succ := util.NewPeerID(convert(successor)) | ||
60 | |||
61 | ok, err := curr.Verify(sd, sig) | ||
62 | if err != nil { | ||
63 | t.Fatal(err) | ||
64 | } | ||
65 | if !ok { | ||
66 | t.Logf("Pred: %s", pred.Short()) | ||
67 | t.Logf("Sign: %s", curr.Short()) | ||
68 | t.Logf("Succ: %s", succ.Short()) | ||
69 | t.Error("Verify NOT OK:") | ||
70 | } | ||
71 | } | ||
diff --git a/src/gnunet/service/dht/path/handling.go b/src/gnunet/service/dht/path/handling.go index 4040511..7ad91df 100644 --- a/src/gnunet/service/dht/path/handling.go +++ b/src/gnunet/service/dht/path/handling.go | |||
@@ -19,11 +19,10 @@ | |||
19 | package path | 19 | package path |
20 | 20 | ||
21 | import ( | 21 | import ( |
22 | "bytes" | ||
23 | "encoding/hex" | ||
24 | "fmt" | ||
25 | "gnunet/crypto" | 22 | "gnunet/crypto" |
23 | "gnunet/enums" | ||
26 | "gnunet/util" | 24 | "gnunet/util" |
25 | "strings" | ||
27 | 26 | ||
28 | "github.com/bfix/gospel/data" | 27 | "github.com/bfix/gospel/data" |
29 | "github.com/bfix/gospel/logger" | 28 | "github.com/bfix/gospel/logger" |
@@ -33,17 +32,11 @@ import ( | |||
33 | // Path handling | 32 | // Path handling |
34 | //---------------------------------------------------------------------- | 33 | //---------------------------------------------------------------------- |
35 | 34 | ||
36 | // path flags | ||
37 | const ( | ||
38 | PathTruncated = 1 | ||
39 | PathLastHop = 2 | ||
40 | ) | ||
41 | |||
42 | // Path is the complete list of verified hops a message travelled. | 35 | // Path is the complete list of verified hops a message travelled. |
43 | // It also keeps the associated block hash and expiration time of | 36 | // It also keeps the associated block hash and expiration time of |
44 | // the request for signature verification purposes. | 37 | // the request for signature verification purposes. |
45 | type Path struct { | 38 | type Path struct { |
46 | Flags uint32 `order:"big"` // flags | 39 | Flags uint16 `order:"big"` // flags |
47 | BlkHash *crypto.HashCode `` // block hash value | 40 | BlkHash *crypto.HashCode `` // block hash value |
48 | Expire util.AbsoluteTime `` // expiration time | 41 | Expire util.AbsoluteTime `` // expiration time |
49 | TruncOrigin *util.PeerID `opt:"(IsUsed)"` // truncated origin (optional) | 42 | TruncOrigin *util.PeerID `opt:"(IsUsed)"` // truncated origin (optional) |
@@ -58,9 +51,9 @@ type Path struct { | |||
58 | func (p *Path) IsUsed(field string) bool { | 51 | func (p *Path) IsUsed(field string) bool { |
59 | switch field { | 52 | switch field { |
60 | case "TruncOrigin": | 53 | case "TruncOrigin": |
61 | return p.Flags&PathTruncated != 0 | 54 | return p.Flags&enums.DHT_RO_TRUNCATED != 0 |
62 | case "LastSig", "LastHop": | 55 | case "LastSig", "LastHop": |
63 | return p.Flags&PathLastHop != 0 | 56 | return p.Flags&enums.DHT_RO_RECORD_ROUTE != 0 |
64 | } | 57 | } |
65 | return false | 58 | return false |
66 | } | 59 | } |
@@ -128,7 +121,7 @@ func (p *Path) Clone() *Path { | |||
128 | // NewElement creates a new path element from data | 121 | // NewElement creates a new path element from data |
129 | func (p *Path) NewElement(pred, signer, succ *util.PeerID) *Element { | 122 | func (p *Path) NewElement(pred, signer, succ *util.PeerID) *Element { |
130 | return &Element{ | 123 | return &Element{ |
131 | elementData: elementData{ | 124 | _ElementData: _ElementData{ |
132 | Expire: p.Expire, | 125 | Expire: p.Expire, |
133 | BlockHash: p.BlkHash, | 126 | BlockHash: p.BlkHash, |
134 | PeerPredecessor: pred, | 127 | PeerPredecessor: pred, |
@@ -155,7 +148,7 @@ func (p *Path) Add(elem *Element) { | |||
155 | // update last hop signature | 148 | // update last hop signature |
156 | p.LastSig = elem.Signature | 149 | p.LastSig = elem.Signature |
157 | p.LastHop = elem.Signer | 150 | p.LastHop = elem.Signer |
158 | p.Flags |= PathLastHop | 151 | p.Flags |= enums.DHT_RO_RECORD_ROUTE |
159 | } | 152 | } |
160 | 153 | ||
161 | // Verify path: process list entries from right to left (decreasing index). | 154 | // Verify path: process list entries from right to left (decreasing index). |
@@ -181,6 +174,7 @@ func (p *Path) Verify(local *util.PeerID) { | |||
181 | pe := p.NewElement(pred, p.LastHop, local) | 174 | pe := p.NewElement(pred, p.LastHop, local) |
182 | ok, err := pe.Verify(p.LastSig) | 175 | ok, err := pe.Verify(p.LastSig) |
183 | if err != nil || !ok { | 176 | if err != nil || !ok { |
177 | logger.Println(logger.WARN, "[path] Dropping path (invalid last signature)") | ||
184 | // remove last hop signature and truncated origin; reset flags | 178 | // remove last hop signature and truncated origin; reset flags |
185 | p.LastSig = nil | 179 | p.LastSig = nil |
186 | p.LastHop = nil | 180 | p.LastHop = nil |
@@ -188,79 +182,79 @@ func (p *Path) Verify(local *util.PeerID) { | |||
188 | p.Flags = 0 | 182 | p.Flags = 0 |
189 | } | 183 | } |
190 | return | 184 | return |
191 | } else { | 185 | } |
192 | // yes: process list of path elements | 186 | // yes: process list of path elements |
193 | signer := p.LastHop | 187 | signer := p.LastHop |
194 | sig := p.LastSig | 188 | sig := p.LastSig |
195 | succ := local | 189 | succ := local |
196 | num := len(p.List) | 190 | num := len(p.List) |
197 | var pred *util.PeerID | 191 | var pred *util.PeerID |
198 | for i := num - 1; i >= 0; i-- { | 192 | for i := num - 1; i >= 0; i-- { |
199 | if i == -1 { | 193 | if i == -1 { |
200 | if p.TruncOrigin != nil { | 194 | if p.TruncOrigin != nil { |
201 | pred = p.TruncOrigin | 195 | pred = p.TruncOrigin |
202 | } else { | ||
203 | pred = util.NewPeerID(nil) | ||
204 | } | ||
205 | } else { | 196 | } else { |
206 | pred = p.List[i].Signer | 197 | pred = util.NewPeerID(nil) |
207 | } | 198 | } |
208 | pe := p.NewElement(pred, signer, succ) | 199 | } else { |
209 | ok, err := pe.Verify(sig) | 200 | pred = p.List[i].Signer |
210 | if err != nil || !ok { | 201 | } |
211 | // we need to truncate: | 202 | pe := p.NewElement(pred, signer, succ) |
212 | logger.Printf(logger.WARN, "[path] Truncating path (invalid signature at hop %d)", i) | 203 | ok, err := pe.Verify(sig) |
204 | if err != nil || !ok { | ||
205 | // we need to truncate: | ||
206 | logger.Printf(logger.WARN, "[path] Truncating path (invalid signature at hop %d)", i) | ||
213 | 207 | ||
214 | // are we at the end of the list? | 208 | // are we at the end of the list? |
215 | if i == num-1 { | 209 | if i == num-1 { |
216 | // yes: the last hop signature failed -> reset path | 210 | // yes: the last hop signature failed -> reset path |
217 | p.LastSig = nil | 211 | p.LastSig = nil |
218 | p.LastHop = nil | 212 | p.LastHop = nil |
219 | p.TruncOrigin = nil | 213 | p.TruncOrigin = nil |
220 | p.Flags = 0 | 214 | p.Flags = 0 |
221 | p.List = make([]*Entry, 0) | 215 | p.List = make([]*Entry, 0) |
222 | return | ||
223 | } | ||
224 | // trim list | ||
225 | p.Flags |= PathTruncated | ||
226 | p.TruncOrigin = signer | ||
227 | size := num - 2 - i | ||
228 | list := make([]*Entry, size) | ||
229 | if size > 0 { | ||
230 | copy(list, p.List[i+2:]) | ||
231 | } | ||
232 | p.List = list | ||
233 | return | 216 | return |
234 | } | 217 | } |
235 | // check next path element | 218 | // trim list |
236 | succ = signer | 219 | p.Flags |= enums.DHT_RO_TRUNCATED |
237 | signer = pred | 220 | p.TruncOrigin = signer |
238 | if i != -1 { | 221 | size := num - 2 - i |
239 | sig = p.List[i].Signature | 222 | list := make([]*Entry, size) |
223 | if size > 0 { | ||
224 | copy(list, p.List[i+2:]) | ||
240 | } | 225 | } |
226 | p.List = list | ||
227 | return | ||
228 | } | ||
229 | // check next path element | ||
230 | succ = signer | ||
231 | signer = pred | ||
232 | if i != -1 { | ||
233 | sig = p.List[i].Signature | ||
241 | } | 234 | } |
242 | } | 235 | } |
243 | } | 236 | } |
244 | 237 | ||
245 | // String returs a uman-readbale representation | 238 | // String returns a human-readable representation |
246 | func (p *Path) String() string { | 239 | func (p *Path) String() string { |
247 | buf := new(bytes.Buffer) | 240 | var hops []string |
248 | s := "0" | 241 | if p != nil { |
249 | if p.TruncOrigin != nil { | 242 | if p.TruncOrigin != nil { |
250 | s = p.TruncOrigin.String() | 243 | hops = append(hops, p.TruncOrigin.Short()) |
251 | } | 244 | } |
252 | buf.WriteString(fmt.Sprintf("{to=%s, (%d)[", s, len(p.List))) | 245 | for _, e := range p.List { |
253 | for _, e := range p.List { | 246 | hops = append(hops, e.Signer.Short()) |
254 | buf.WriteString(e.String()) | 247 | } |
255 | } | 248 | if p.LastHop != nil { |
256 | s = "0" | 249 | hops = append(hops, p.LastHop.Short()) |
257 | if p.LastSig != nil { | 250 | } |
258 | s = hex.EncodeToString(p.LastSig.Bytes()) | ||
259 | } | 251 | } |
260 | num := len(s) | 252 | // trim to sensible length for display |
261 | if num > 16 { | 253 | if num := len(hops); num > 8 { |
262 | s = s[:8] + ".." + s[num-8:] | 254 | trim := make([]string, 9) |
255 | copy(trim[:4], hops[:4]) | ||
256 | trim[4] = "..." | ||
257 | copy(trim[5:], hops[num-5:]) | ||
263 | } | 258 | } |
264 | buf.WriteString(fmt.Sprintf("], ls=%s}", s)) | 259 | return "[" + strings.Join(hops, "-") + "]" |
265 | return buf.String() | ||
266 | } | 260 | } |