// Dispatch can handle timeouts func (p *Propagate) Dispatch() error { process := true log.Lvl4(p.ServerIdentity()) for process { p.Lock() timeout := time.Millisecond * time.Duration(p.sd.Msec) p.Unlock() select { case msg := <-p.ChannelSD: log.Lvl3(p.ServerIdentity(), "Got data from", msg.ServerIdentity, "and setting timeout to", msg.Msec) p.sd.Msec = msg.Msec if p.onData != nil { _, netMsg, err := network.UnmarshalRegistered(msg.Data) if err == nil { p.onData(netMsg) } } if !p.IsRoot() { log.Lvl3(p.ServerIdentity(), "Sending to parent") p.SendToParent(&PropagateReply{}) } if p.IsLeaf() { process = false } else { log.Lvl3(p.ServerIdentity(), "Sending to children") p.SendToChildren(&msg.PropagateSendData) } case <-p.ChannelReply: p.received++ log.Lvl4(p.ServerIdentity(), "received:", p.received, p.subtreeCount) if !p.IsRoot() { p.SendToParent(&PropagateReply{}) } if p.received == p.subtreeCount { process = false } case <-time.After(timeout): _, a, err := network.UnmarshalRegistered(p.sd.Data) log.Fatalf("Timeout of %s reached. %v %s", timeout, a, err) process = false } } if p.IsRoot() { if p.onDoneCb != nil { p.onDoneCb(p.received + 1) } } p.Done() return nil }
// loadConfig will try to load the configuration and `fatal` if it is there but // not valid. If the config-file is missing altogether, loaded will be false and // an empty config-file will be returned. func loadConfig(c *cli.Context) (cfg *ciscConfig, loaded bool) { cfg = &ciscConfig{Identity: &identity.Identity{}} loaded = true configFile := getConfig(c) log.Lvl2("Loading from", configFile) buf, err := ioutil.ReadFile(configFile) if err != nil { if os.IsNotExist(err) { return } log.ErrFatal(err) } _, msg, err := network.UnmarshalRegistered(buf) log.ErrFatal(err) cfg, loaded = msg.(*ciscConfig) cfg.Identity.Client = onet.NewClient(identity.ServiceName) for _, f := range cfg.Follow { f.Client = onet.NewClient(identity.ServiceName) } if !loaded { log.Fatal("Wrong message-type in config-file") } return }
// propagateSkipBlock saves a new skipblock to the identity func (s *Service) propagateSkipBlockHandler(msg network.Body) { log.Lvlf4("Got msg %+v %v", msg, reflect.TypeOf(msg).String()) usb, ok := msg.(*UpdateSkipBlock) if !ok { log.Error("Wrong message-type") return } sid := s.getIdentityStorage(usb.ID) if sid == nil { log.Error("Didn't find entity in", s) return } sid.Lock() defer sid.Unlock() skipblock := msg.(*UpdateSkipBlock).Latest _, msgLatest, err := network.UnmarshalRegistered(skipblock.Data) if err != nil { log.Error(err) return } al, ok := msgLatest.(*Config) if !ok { log.Error(err) return } sid.Data = skipblock sid.Latest = al sid.Proposed = nil }
func main() { network.RegisterPacketType(&Database{}) app := cli.NewApp() app.Name = "Guard" app.Usage = "Get and print status of all servers of a file." app.Flags = []cli.Flag{ cli.StringFlag{ Name: "group, gd", Value: "group.toml", Usage: "Cothority group definition in `FILE.toml`", }, cli.IntFlag{ Name: "debug, d", Value: 0, Usage: "debug-level: `integer`: 1 for terse, 5 for maximal", }, } app.Commands = []cli.Command{ { Name: "setpass", Aliases: []string{"s"}, Usage: "Setup the configuration for the server (interactive)", Action: setpass, }, { Name: "setup", Aliases: []string{"su"}, Usage: "Saves the cothority group-toml to the configuration", ArgsUsage: "Give group definition", Action: setup, }, { Name: "recover", Aliases: []string{"r"}, Usage: "Gets the password back from the guards", Action: get, }, } app.Before = func(c *cli.Context) error { b, err := ioutil.ReadFile("config.bin") if os.IsNotExist(err) { return nil } log.ErrFatal(err, "The config.bin file threw an error") _, msg, err := network.UnmarshalRegistered(b) log.ErrFatal(err, "UnmarshalRegistered messeed up") var ok bool db, ok = msg.(*Database) if !ok { log.Fatal("The message was improperly converted") } return nil } app.Run(os.Args) }
// NewIdentityFromStream reads the configuration of that client from // any stream func NewIdentityFromStream(in io.Reader) (*Identity, error) { data, err := ioutil.ReadAll(in) if err != nil { return nil, err } _, i, err := network.UnmarshalRegistered(data) if err != nil { return nil, err } id := i.(*Data) identity := &Identity{ Client: onet.NewClient(ServiceName), Data: *id, } return identity, nil }
// Tries to load the configuration and updates if a configuration // is found, else it returns an error. func (s *Service) tryLoad() error { configFile := s.path + "/identity.bin" b, err := ioutil.ReadFile(configFile) if err != nil && !os.IsNotExist(err) { return fmt.Errorf("Error while reading %s: %s", configFile, err) } if len(b) > 0 { _, msg, err := network.UnmarshalRegistered(b) if err != nil { return fmt.Errorf("Couldn't unmarshal: %s", err) } log.Lvl3("Successfully loaded") s.StorageMap = msg.(*StorageMap) } return nil }
// bftVerify takes a message and verifies it's valid func (s *Service) bftVerify(msg []byte, data []byte) bool { log.Lvlf4("%s verifying block %x", s.ServerIdentity(), msg) s.testVerify = true _, sbN, err := network.UnmarshalRegistered(data) if err != nil { log.Error("Couldn't unmarshal SkipBlock", data) return false } sb := sbN.(*SkipBlock) if !sb.Hash.Equal(SkipBlockID(msg)) { log.Lvlf2("Data skipBlock different from msg %x %x", msg, sb.Hash) return false } f, ok := s.verifiers[sb.VerifierID] if !ok { log.Lvlf2("Found no user verification for %x", sb.VerifierID) return false } return f(msg, sb) }
// ProposeVote takes int account a vote for the proposed config. It also verifies // that the voter is in the latest config. // An empty signature signifies that the vote has been rejected. func (s *Service) ProposeVote(v *ProposeVote) (network.Body, onet.ClientError) { log.Lvl2(s, "Voting on proposal") // First verify if the signature is legitimate sid := s.getIdentityStorage(v.ID) if sid == nil { return nil, onet.NewClientErrorCode(ErrorBlockMissing, "Didn't find identity") } // Putting this in a function because of the lock which needs to be held // over all calls that might return an error. cerr := func() onet.ClientError { sid.Lock() defer sid.Unlock() log.Lvl3("Voting on", sid.Proposed.Device) owner, ok := sid.Latest.Device[v.Signer] if !ok { return onet.NewClientErrorCode(ErrorAccountMissing, "Didn't find signer") } if sid.Proposed == nil { return onet.NewClientErrorCode(ErrorConfigMissing, "No proposed block") } hash, err := sid.Proposed.Hash() if err != nil { return onet.NewClientErrorCode(ErrorOnet, "Couldn't get hash") } if _, exists := sid.Votes[v.Signer]; exists { return onet.NewClientErrorCode(ErrorVoteDouble, "Already voted for that block") } log.Lvl3(v.Signer, "voted", v.Signature) if v.Signature != nil { err = crypto.VerifySchnorr(network.Suite, owner.Point, hash, *v.Signature) if err != nil { return onet.NewClientErrorCode(ErrorVoteSignature, "Wrong signature: "+err.Error()) } } return nil }() if cerr != nil { return nil, cerr } // Propagate the vote _, err := s.propagateConfig(sid.Root.Roster, v, propagateTimeout) if err != nil { return nil, onet.NewClientErrorCode(ErrorOnet, cerr.Error()) } if len(sid.Votes) >= sid.Latest.Threshold || len(sid.Votes) == len(sid.Latest.Device) { // If we have enough signatures, make a new data-skipblock and // propagate it log.Lvl3("Having majority or all votes") // Making a new data-skipblock log.Lvl3("Sending data-block with", sid.Proposed.Device) reply, cerr := s.skipchain.ProposeData(sid.Root, sid.Data, sid.Proposed) if cerr != nil { return nil, cerr } _, msg, _ := network.UnmarshalRegistered(reply.Latest.Data) log.Lvl3("SB signed is", msg.(*Config).Device) usb := &UpdateSkipBlock{ ID: v.ID, Latest: reply.Latest, } _, err = s.propagateSkipBlock(sid.Root.Roster, usb, propagateTimeout) if err != nil { return nil, onet.NewClientErrorCode(ErrorOnet, cerr.Error()) } s.save() return &ProposeVoteReply{sid.Data}, nil } return nil, nil }