refactor: add isDomainNameAndNotPeerID
This ensures we exclude valid PeerIDs from code paths that require DNSLink names. Ref. https://github.com/ipfs/go-ipfs/pull/8071#pullrequestreview-639409245
Marcin Rataj committed
Apr 21, 2021 at 20:36 UTC
28d4d9b327b83cef407a8a79e7162ab54bcfa63d
2 files changed
+36
-5
core/corehttp/hostname.go
+16
-4
@@ -349,15 +349,27 @@ func knownSubdomainDetails(hostname string, knownGateways gatewayHosts) (gw *con
349
return nil, "", "", "", false
350
}
351
352
+// isDomainNameAndNotPeerID returns bool if string looks like a valid DNS name AND is not a PeerID
353
+func isDomainNameAndNotPeerID(hostname string) bool {
354
+ if len(hostname) == 0 {
355
+ return false
356
+ }
357
+ if _, err := peer.Decode(hostname); err == nil {
358
+ return false
359
+ }
360
+ _, ok := dns.IsDomainName(hostname)
361
+ return ok
362
+}
363
+
364
// isDNSLinkName returns bool if a valid DNS TXT record exist for provided host
365
func isDNSLinkName(ctx context.Context, ipfs iface.CoreAPI, host string) bool {
354
- fqdn := stripPort(host)
366
+ dnslinkName := stripPort(host)
367
356
- if _, ok := dns.IsDomainName(fqdn); !ok && len(fqdn) == 0 {
368
+ if !isDomainNameAndNotPeerID(dnslinkName) {
369
return false
370
}
371
360
- name := "/ipns/" + fqdn
372
+ name := "/ipns/" + dnslinkName
373
// check if DNSLink exists
374
depth := options.Name.ResolveOption(nsopts.Depth(1))
375
_, err := ipfs.Name().Resolve(ctx, name, depth)
@@ -476,7 +488,7 @@ func toSubdomainURL(hostname, path string, r *http.Request, ipfs iface.CoreAPI)
488
}
489
490
// Normalize problematic PeerIDs (eg. ed25519+identity) to CID representation
479
- if _, ok := dns.IsDomainName(rootID); !ok && isPeerIDNamespace(ns) {
491
+ if isPeerIDNamespace(ns) && !isDomainNameAndNotPeerID(rootID) {
492
peerID, err := peer.Decode(rootID)
493
// Note: PeerID CIDv1 with protobuf multicodec will fail, but we fix it
494
// in the next block
core/corehttp/hostname_test.go
+20
-1
@@ -55,7 +55,7 @@ func TestToSubdomainURL(t *testing.T) {
55
{httpRequest, "localhost", "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", "http://k2k4r8n0flx3ra0y5dr8fmyvwbzy3eiztmtq6th694k5a3rznayp3e4o.ipns.localhost/", nil},
56
{httpRequest, "localhost", "/ipns/bafybeickencdqw37dpz3ha36ewrh4undfjt2do52chtcky4rxkj447qhdm", "http://k2k4r8l9ja7hkzynavdqup76ou46tnvuaqegbd04a4o1mpbsey0meucb.ipns.localhost/", nil},
57
// PeerID: ed25519+identity multihash → CIDv1Base36
58
- {httpRequest, "localhost", "/ipns/12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5", "http://12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5.ipns.localhost/", nil},
58
+ {httpRequest, "localhost", "/ipns/12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5", "http://k51qzi5uqu5di608geewp3nqkg0bpujoasmka7ftkyxgcm3fh1aroup0gsdrna.ipns.localhost/", nil},
59
{httpRequest, "sub.localhost", "/ipfs/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", "http://bafybeif7a7gdklt6hodwdrmwmxnhksctcuav6lfxlcyfz4khzl3qfmvcgu.ipfs.sub.localhost/", nil},
60
// HTTPS requires DNSLink name to fit in a single DNS label – see "Option C" from https://github.com/ipfs/in-web-browsers/issues/169
61
{httpRequest, "dweb.link", "/ipns/dnslink.long-name.example.com", "http://dnslink.long-name.example.com.ipns.dweb.link/", nil},
@@ -144,6 +144,25 @@ func TestHasPrefix(t *testing.T) {
144
}
145
}
146
147
+func TestIsDomainNameAndNotPeerID(t *testing.T) {
148
+ for _, test := range []struct {
149
+ hostname string
150
+ out bool
151
+ }{
152
+ {"", false},
153
+ {"example.com", true},
154
+ {"non-icann.something", true},
155
+ {"..", false},
156
+ {"12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5", false}, // valid peerid
157
+ {"k51qzi5uqu5di608geewp3nqkg0bpujoasmka7ftkyxgcm3fh1aroup0gsdrna", false}, // valid peerid
158
+ } {
159
+ out := isDomainNameAndNotPeerID(test.hostname)
160
+ if out != test.out {
161
+ t.Errorf("(%s) returned '%t', expected '%t'", test.hostname, out, test.out)
162
+ }
163
+ }
164
+}
165
+
166
func TestPortStripping(t *testing.T) {
167
for _, test := range []struct {
168
in string