// getCACert returns the ca certificate (verified). certHash is from // GetConfig().Config["CACertHash"] func getCACert(configURL string, certHash string, timeout int64) ([]byte, error) { c := &http.Client{Timeout: time.Second * time.Duration(timeout)} resp, err := c.Get(fixURL(configURL) + "cacert") if err != nil { return nil, err } p, err := readBody(resp.Body) if err != nil { return nil, err } testHash, err := cahash.Hash(p) if err != nil { return nil, err } certHashb, err := hex.DecodeString(certHash) if err != nil { return nil, err } if !bytes.Equal(testHash, certHashb) { return nil, ErrHashWrong } return p, nil }
// Update a configuration structure. func (c *Config) Update() error { var err error var cert *sortedmap.SignedMap var myCAhash, certHashb []byte var hisHash string var ok bool if c.Timeout == 0 { c.Timeout = 30 } ts := roundrobin.ParseServers(c.URLList) sort.Sort(ts) c.servers = ts.Order() if len(c.servers) < 1 { return ErrNoServers } if c.LastSignDate == 0 { c.LastSignDate = uint64(times.Now() - skew) } GetConfigLoop: for ; c.curServer < len(c.servers); c.curServer++ { cert, err = getConfig(c.servers[c.curServer], c.PublicKey, c.LastSignDate, c.Timeout) if err == nil { break GetConfigLoop } } if err != nil { return err } // Change server ordering to make working and untested first c.servers = append(c.servers[c.curServer:], c.servers[:c.curServer]...) c.curServer = 0 if hisHash, ok = cert.Config["CACertHash"]; !ok { c.Map = cert.Config c.LastSignDate = cert.SignDate return nil } if certHashb, err = hex.DecodeString(hisHash); err != nil { return err } if c.CACert != nil { if myCAhash, err = cahash.Hash(c.CACert); err != nil { return err } } if !bytes.Equal(myCAhash, certHashb) { CALoop: for ; c.curServer < len(c.servers); c.curServer++ { c.CACert, err = getCACert(c.servers[c.curServer], hisHash, c.Timeout) if err == nil { break CALoop } } } if err != nil { return err } c.Map = cert.Config c.LastSignDate = cert.SignDate return nil }