Verify previous names in client
This commit is contained in:
parent
526b73aa99
commit
67c05fd4a2
52
client.go
52
client.go
@ -100,11 +100,45 @@ func (c Client) lookup(resource, id string, all bool, dest any) error {
|
|||||||
pubkeySaved := false
|
pubkeySaved := false
|
||||||
pubkey, err := c.GetPubkey(pfdURL.Host)
|
pubkey, err := c.GetPubkey(pfdURL.Host)
|
||||||
if errors.Is(err, ErrPubkeyNotFound) {
|
if errors.Is(err, ErrPubkeyNotFound) {
|
||||||
info, _, err := getServerInfo(pfdURL.Scheme, pfdURL.Host)
|
data, sig, prevSigs, err := getServerInfo(pfdURL.Scheme, pfdURL.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var info serverInfoData
|
||||||
|
err = json.Unmarshal(data, &info)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this server is advertising previous names, make sure
|
||||||
|
// we verify that it's telling the truth by checking the whether
|
||||||
|
// any of its signatures match using the pubkeys of the previous names.
|
||||||
|
if len(info.PreviousNames) > 0 {
|
||||||
|
for _, prevName := range info.PreviousNames {
|
||||||
|
pubkey, err = c.GetPubkey(prevName)
|
||||||
|
if errors.Is(err, ErrPubkeyNotFound) {
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ed25519.Verify(pubkey, data, sig) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, prevSig := range prevSigs {
|
||||||
|
if ed25519.Verify(pubkey, data, prevSig) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't broken out of the loop by now, this
|
||||||
|
// name could not be verified, so return an error.
|
||||||
|
return ErrSignatureMismatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pubkey, err = base64.StdEncoding.DecodeString(info.PublicKey)
|
pubkey, err = base64.StdEncoding.DecodeString(info.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -229,20 +263,24 @@ func serverInfoReq(scheme, host string) (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getServerInfo retrieves server information.
|
// getServerInfo retrieves server information.
|
||||||
func getServerInfo(scheme, host string) (serverInfoData, [][]byte, error) {
|
func getServerInfo(scheme, host string) (data, sig []byte, prevSigs [][]byte, err error) {
|
||||||
res, err := serverInfoReq(scheme, host)
|
res, err := serverInfoReq(scheme, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serverInfoData{}, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
if err := checkResp(res, "getServerInfo"); err != nil {
|
if err := checkResp(res, "getServerInfo"); err != nil {
|
||||||
return serverInfoData{}, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out serverInfoData
|
sig, err = getSignature(res)
|
||||||
err = json.NewDecoder(io.LimitReader(res.Body, responseSizeLimit)).Decode(&out)
|
if err != nil {
|
||||||
return out, getPrevSignatures(res), err
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err = io.ReadAll(io.LimitReader(res.Body, responseSizeLimit))
|
||||||
|
return data, sig, getPrevSignatures(res), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPrevSignatures extracts previous signatures from a response.
|
// getPrevSignatures extracts previous signatures from a response.
|
||||||
|
Loading…
Reference in New Issue
Block a user