From e16155e22a8f00bdbb4acb0a108c605065f9ba3f Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Fri, 26 Jan 2018 20:38:31 +0100 Subject: [PATCH] DoHstamps --- dnscrypt-proxy/sources.go | 2 +- dnscrypt-proxy/stamps.go | 106 ++++++++++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/dnscrypt-proxy/sources.go b/dnscrypt-proxy/sources.go index 139fb50f..6bb3392d 100644 --- a/dnscrypt-proxy/sources.go +++ b/dnscrypt-proxy/sources.go @@ -198,7 +198,7 @@ func (source *Source) parseV1(prefix string) ([]RegisteredServer, error) { if strings.EqualFold(record[8], "yes") { props |= ServerInformalPropertyNoLog } - stamp, err := NewServerStampFromDNSCryptLegacy(serverAddrStr, serverPkStr, providerName, props) + stamp, err := NewDNSCryptServerStampFromLegacy(serverAddrStr, serverPkStr, providerName, props) if err != nil { return registeredServers, err } diff --git a/dnscrypt-proxy/stamps.go b/dnscrypt-proxy/stamps.go index 5e1fa866..901777c3 100644 --- a/dnscrypt-proxy/stamps.go +++ b/dnscrypt-proxy/stamps.go @@ -9,6 +9,7 @@ import ( "net" "strings" + "github.com/jedisct1/dlog" "golang.org/x/crypto/ed25519" ) @@ -23,13 +24,14 @@ const ( type ServerStamp struct { serverAddrStr string serverPk []uint8 + hash []uint8 providerName string path string props ServerInformalProperties proto StampProtoType } -func NewServerStampFromDNSCryptLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) { +func NewDNSCryptServerStampFromLegacy(serverAddrStr string, serverPkStr string, providerName string, props ServerInformalProperties) (ServerStamp, error) { if net.ParseIP(serverAddrStr) != nil { serverAddrStr = fmt.Sprintf("%s:%d", serverAddrStr, DefaultPort) } @@ -46,22 +48,29 @@ func NewServerStampFromDNSCryptLegacy(serverAddrStr string, serverPkStr string, }, nil } -// id(u8) props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName - func NewServerStampFromString(stampStr string) (ServerStamp, error) { - stamp := ServerStamp{} if !strings.HasPrefix(stampStr, "sdns://") && !strings.HasPrefix(stampStr, "dnsc://") { - return stamp, errors.New("Stamps are expected to start with sdns://") + return ServerStamp{}, errors.New("Stamps are expected to start with sdns://") } bin, err := base64.RawURLEncoding.DecodeString(stampStr[7:]) if err != nil { - return stamp, err + return ServerStamp{}, err } - if len(bin) < 24 { - return stamp, errors.New("Stamp is too short") + if len(bin) < 1 { + return ServerStamp{}, errors.New("Stamp is too short") } if bin[0] != uint8(StampProtoTypeDNSCrypt) { - return stamp, errors.New("Unsupported stamp version") + return newDNSCryptServerStamp(bin) + } + return ServerStamp{}, errors.New("Unsupported stamp version or protocol") +} + +// id(u8)=0x02 props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName + +func newDNSCryptServerStamp(bin []byte) (ServerStamp, error) { + stamp := ServerStamp{} + if len(bin) < 24 { + return stamp, errors.New("Stamp is too short") } stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9])) binLen := len(bin) @@ -97,7 +106,64 @@ func NewServerStampFromString(stampStr string) (ServerStamp, error) { return stamp, nil } +// id(u8)=0x02 props addrLen(1) serverAddr hashLen(1) hash providerNameLen(1) providerName pathLen(1) path + +func newDoHServerStamp(bin []byte) (ServerStamp, error) { + stamp := ServerStamp{} + + stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9])) + binLen := len(bin) + pos := 9 + + len := int(bin[pos]) + if len >= binLen-pos { + return stamp, errors.New("Invalid stamp") + } + pos++ + stamp.serverAddrStr = string(bin[pos : pos+len]) + pos += len + + len = int(bin[pos]) + if len >= binLen-pos { + return stamp, errors.New("Invalid stamp") + } + pos++ + stamp.hash = bin[pos : pos+len] + pos += len + + len = int(bin[pos]) + if len >= binLen-pos { + return stamp, errors.New("Invalid stamp") + } + pos++ + stamp.providerName = string(bin[pos : pos+len]) + pos += len + + len = int(bin[pos]) + if len >= binLen-pos { + return stamp, errors.New("Invalid stamp") + } + pos++ + stamp.path = string(bin[pos : pos+len]) + pos += len + + if pos != binLen { + return stamp, errors.New("Invalid stamp (garbage after end)") + } + return stamp, nil +} + func (stamp *ServerStamp) String() string { + if stamp.proto == StampProtoTypeDNSCrypt { + return stamp.dnsCryptString() + } else if stamp.proto == StampProtoTypeDoH { + return stamp.dohString() + } + dlog.Fatal("Unsupported protocol") + return "" +} + +func (stamp *ServerStamp) dnsCryptString() string { bin := make([]uint8, 9) bin[0] = uint8(StampProtoTypeDNSCrypt) binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props)) @@ -115,3 +181,25 @@ func (stamp *ServerStamp) String() string { return "sdns://" + str } + +func (stamp *ServerStamp) dohString() string { + bin := make([]uint8, 9) + bin[0] = uint8(StampProtoTypeDoH) + binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props)) + + bin = append(bin, uint8(len(stamp.serverAddrStr))) + bin = append(bin, []uint8(stamp.serverAddrStr)...) + + bin = append(bin, uint8(len(stamp.hash))) + bin = append(bin, []uint8(stamp.hash)...) + + bin = append(bin, uint8(len(stamp.providerName))) + bin = append(bin, []uint8(stamp.providerName)...) + + bin = append(bin, uint8(len(stamp.path))) + bin = append(bin, []uint8(stamp.path)...) + + str := base64.RawURLEncoding.EncodeToString(bin) + + return "sdns://" + str +}