Пример #1
0
func (s *Server) revocation(from *[32]byte, signedRevocation *pond.SignedRevocation) *pond.Reply {
	account, ok := s.getAccount(from)
	if !ok {
		return &pond.Reply{Status: pond.Reply_NO_ACCOUNT.Enum()}
	}

	revocation, ok := new(bbssig.Revocation).Unmarshal(signedRevocation.Revocation.Revocation)
	if !ok {
		return &pond.Reply{Status: pond.Reply_CANNOT_PARSE_REVOCATION.Enum()}
	}

	// First check that the account doesn't have too many revocations
	// stored.

	revPath := account.RevocationPath()
	os.MkdirAll(revPath, 0777)

	revDir, err := os.Open(revPath)
	if err != nil {
		log.Printf("Failed to open %s: %s", revPath, err)
		return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
	}
	defer revDir.Close()

	ents, err := revDir.Readdir(0)
	if err != nil {
		log.Printf("Failed to read %s: %s", revDir, err)
		return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
	}

	if len(ents) > maxRevocations {
		// Delete the oldest revocation.
		names := make([]string, 0, len(ents))
		for _, ent := range ents {
			names = append(names, ent.Name())
		}
		sort.Strings(names)
		path := filepath.Join(revPath, names[0])
		if err := os.Remove(path); err != nil {
			log.Printf("Failed to remove %s: %s", path, err)
			return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
		}
	}

	path := filepath.Join(revPath, fmt.Sprintf("%08x", *signedRevocation.Revocation.Generation))
	revBytes, err := proto.Marshal(signedRevocation)
	if err != nil {
		log.Printf("Failed to serialise revocation: %s", err)
		return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
	}

	if err := ioutil.WriteFile(path, revBytes, 0666); err != nil {
		log.Printf("Failed to write revocation file: %s", err)
		return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
	}

	group := account.Group()
	if group == nil {
		return &pond.Reply{Status: pond.Reply_INTERNAL_ERROR.Enum()}
	}
	groupCopy, _ := new(bbssig.Group).Unmarshal(group.Marshal())
	groupCopy.Update(revocation)

	account.Lock()
	defer account.Unlock()

	account.group = groupCopy
	groupPath := filepath.Join(account.Path(), "group")
	if err := ioutil.WriteFile(groupPath, groupCopy.Marshal(), 0600); err != nil {
		log.Printf("failed to write group file: %s", err)
	}

	return nil
}