DoHstamps

This commit is contained in:
Frank Denis 2018-01-26 20:38:31 +01:00
parent 3bbecdcde7
commit e16155e22a
2 changed files with 98 additions and 10 deletions

View File

@ -198,7 +198,7 @@ func (source *Source) parseV1(prefix string) ([]RegisteredServer, error) {
if strings.EqualFold(record[8], "yes") { if strings.EqualFold(record[8], "yes") {
props |= ServerInformalPropertyNoLog props |= ServerInformalPropertyNoLog
} }
stamp, err := NewServerStampFromDNSCryptLegacy(serverAddrStr, serverPkStr, providerName, props) stamp, err := NewDNSCryptServerStampFromLegacy(serverAddrStr, serverPkStr, providerName, props)
if err != nil { if err != nil {
return registeredServers, err return registeredServers, err
} }

View File

@ -9,6 +9,7 @@ import (
"net" "net"
"strings" "strings"
"github.com/jedisct1/dlog"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
) )
@ -23,13 +24,14 @@ const (
type ServerStamp struct { type ServerStamp struct {
serverAddrStr string serverAddrStr string
serverPk []uint8 serverPk []uint8
hash []uint8
providerName string providerName string
path string path string
props ServerInformalProperties props ServerInformalProperties
proto StampProtoType 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 { if net.ParseIP(serverAddrStr) != nil {
serverAddrStr = fmt.Sprintf("%s:%d", serverAddrStr, DefaultPort) serverAddrStr = fmt.Sprintf("%s:%d", serverAddrStr, DefaultPort)
} }
@ -46,22 +48,29 @@ func NewServerStampFromDNSCryptLegacy(serverAddrStr string, serverPkStr string,
}, nil }, nil
} }
// id(u8) props addrLen(1) serverAddr pkStrlen(1) pkStr providerNameLen(1) providerName
func NewServerStampFromString(stampStr string) (ServerStamp, error) { func NewServerStampFromString(stampStr string) (ServerStamp, error) {
stamp := ServerStamp{}
if !strings.HasPrefix(stampStr, "sdns://") && !strings.HasPrefix(stampStr, "dnsc://") { 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:]) bin, err := base64.RawURLEncoding.DecodeString(stampStr[7:])
if err != nil { if err != nil {
return stamp, err return ServerStamp{}, err
} }
if len(bin) < 24 { if len(bin) < 1 {
return stamp, errors.New("Stamp is too short") return ServerStamp{}, errors.New("Stamp is too short")
} }
if bin[0] != uint8(StampProtoTypeDNSCrypt) { 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])) stamp.props = ServerInformalProperties(binary.LittleEndian.Uint64(bin[1:9]))
binLen := len(bin) binLen := len(bin)
@ -97,7 +106,64 @@ func NewServerStampFromString(stampStr string) (ServerStamp, error) {
return stamp, nil 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 { 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 := make([]uint8, 9)
bin[0] = uint8(StampProtoTypeDNSCrypt) bin[0] = uint8(StampProtoTypeDNSCrypt)
binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props)) binary.LittleEndian.PutUint64(bin[1:9], uint64(stamp.props))
@ -115,3 +181,25 @@ func (stamp *ServerStamp) String() string {
return "sdns://" + str 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
}