func (self *DAG) addNode(node Node) (int, Node) { name := node.Name() if id, ok := self.index[name]; ok { existing := self.nodes[id] newtype := reflect.TypeOf(node) oldtype := reflect.TypeOf(existing) if newtype != oldtype { panic(fmt.Sprintf( "cannot add node '%s' (type %s): there is already a node "+ "with that name, but its type is %s", name, newtype, oldtype)) } return id, existing } if len(self.nodes) != len(self.parents) { panic(fmt.Sprintf( "inconsistent DAG: len(nodes) = %d, len(parents) = %d", len(self.nodes), len(self.parents))) } if node.id() != -1 { panic(fmt.Sprintf( "cannot add node %s to the DAG: it already has id %d", node, node.id())) } id := len(self.nodes) node.setid(id) self.nodes = append(self.nodes, node) self.parents = append(self.parents, bit.New()) self.index[name] = id return id, node }
func NewNaClDecryptorInstance(outbound bool) *NaClDecryptorInstance { di := &NaClDecryptorInstance{usedOffsets: bit.New()} if !outbound { di.nonce[0] |= (1 << 7) } return di }
// Return the set of nodes in this graph with no children. func (self *DAG) FindFinalTargets() *NodeSet { //fmt.Println("FindFinalTargets():") var targets *bit.Set = bit.New() targets.AddRange(0, self.length()) for _, parents := range self.parents { //fmt.Printf(" %d: node=%v, parents=%v\n", id, self.nodes[id], parents) targets.SetAndNot(targets, parents) } //fmt.Printf(" -> targets = %v\n", targets) return (*NodeSet)(targets) }
// Add the same set of parents (source nodes) to many children (target // nodes). func (self *DAG) AddManyParents(targets, sources []Node) { sourceset := bit.New() for _, snode := range sources { sourceset.Add(snode.id()) } for _, tnode := range targets { tid := tnode.id() self.parents[tid].SetOr(self.parents[tid], sourceset) } }
// Return a NodeSet containing all the nodes passed by name. Panic if // any of the names do not exist in this DAG. Mainly for test code. func (self *DAG) MakeNodeSet(names ...string) *NodeSet { result := bit.New() for _, name := range names { id, ok := self.index[name] if !ok { panic("no such node: " + name) } result.Add(id) } return (*NodeSet)(result) }
func NewNaClDecryptor(conn *LocalConnection) *NaClDecryptor { inst := NaClDecryptorInstance{ nonce: nil, previousNonce: nil, usedOffsets: bit.New(), previousUsedOffsets: nil, highestOffsetSeen: 0, nonceChan: make(chan *[24]byte, ChannelSize)} instDF := NaClDecryptorInstance{ nonce: nil, previousNonce: nil, usedOffsets: bit.New(), previousUsedOffsets: nil, highestOffsetSeen: 0, nonceChan: make(chan *[24]byte, ChannelSize)} return &NaClDecryptor{ NonDecryptor: *NewNonDecryptor(conn), instance: &inst, instanceDF: &instDF} }
func (self *DAG) matchPrefix(name string, errs []error) (*bit.Set, []error) { prefix := string(append(([]byte)(name), filepath.Separator)) result := bit.New() for _, trynode := range self.nodes { if self.HasParents(trynode) && strings.HasPrefix(trynode.Name(), prefix) { result.Add(trynode.id()) } } if result.IsEmpty() { errs = append(errs, fmt.Errorf("no targets found matching '%s'", name)) } return result, errs }
func (di *NaClDecryptorInstance) advanceState(seqNo uint64) (int, *bit.Set) { var ( offset = int(seqNo & ((1 << WindowSize) - 1)) window = seqNo >> WindowSize ) switch delta := int64(window - di.currentWindow); { case delta < -1: return offset, nil case delta == -1: return offset, di.previousUsedOffsets default: return offset, di.usedOffsets case delta == +1: di.currentWindow = window di.previousUsedOffsets = di.usedOffsets di.usedOffsets = bit.New() return offset, di.usedOffsets case delta > +1: di.currentWindow = window di.previousUsedOffsets = bit.New() di.usedOffsets = bit.New() return offset, di.usedOffsets } }
// Return the set of nodes in this graph that match the names in // targets. If targets is nil or empty, return all final targets // (nodes with no children). Otherwise, for each name in targets, find // the node with that name. If no such node, find all nodes whose // names start with that name (in the pathname sense: "foo/bar" starts // with "foo", but not with "f"). Each target name with no matches // will result in one error object being appended to the returned // slice of errors. func (self *DAG) MatchTargets(targets []string) (*NodeSet, []error) { if len(targets) == 0 { return self.FindFinalTargets(), nil } result := bit.New() errs := []error{} for _, name := range targets { name = filepath.Clean(name) id, ok := self.index[name] if ok { if self.parents[id].IsEmpty() { errs = append(errs, fmt.Errorf("not a target: '%s'", self.nodes[id].Name())) } else { result.Add(id) } } else { var prefixmatch *bit.Set prefixmatch, errs = self.matchPrefix(name, errs) result.SetOr(result, prefixmatch) } } return (*NodeSet)(result), errs }
func (nd *NaClDecryptor) decrypt(buf []byte) ([]byte, error) { offset := binary.BigEndian.Uint16(buf[:2]) df := (offset & (1 << 15)) != 0 offsetNoFlags := offset & ((1 << 15) - 1) var decState *NaClDecryptorInstance if df { decState = nd.instanceDF } else { decState = nd.instance } var nonce *[24]byte var usedOffsets *bit.Set var ok bool if decState.nonce == nil { if offsetNoFlags > (1 << 13) { // offset is already beyond the first quarter and it's the // first thing we've seen?! I don't think so. return nil, fmt.Errorf("Unexpected offset when decrypting UDP packet") } decState.nonce, ok = <-decState.nonceChan if !ok { return nil, fmt.Errorf("Nonce chan closed") } nonce = decState.nonce usedOffsets = decState.usedOffsets decState.highestOffsetSeen = offsetNoFlags } else { highestOffsetSeen := decState.highestOffsetSeen if offsetNoFlags < (1<<13) && highestOffsetSeen > ((1<<14)+(1<<13)) && (highestOffsetSeen-offsetNoFlags) > ((1<<14)+(1<<13)) { // offset is in the first quarter, highestOffsetSeen is in // the top quarter and under a quarter behind us. We // interpret this as we need to move to the next nonce decState.previousUsedOffsets = decState.usedOffsets decState.usedOffsets = bit.New() decState.previousNonce = decState.nonce decState.nonce, ok = <-decState.nonceChan if !ok { return nil, fmt.Errorf("Nonce chan closed") } decState.highestOffsetSeen = offsetNoFlags nonce = decState.nonce usedOffsets = decState.usedOffsets } else if offsetNoFlags > highestOffsetSeen && (offsetNoFlags-highestOffsetSeen) < (1<<13) { // offset is under a quarter above highestOffsetSeen. This // is ok - maybe some packet loss decState.highestOffsetSeen = offsetNoFlags nonce = decState.nonce usedOffsets = decState.usedOffsets } else if offsetNoFlags <= highestOffsetSeen && (highestOffsetSeen-offsetNoFlags) < (1<<13) { // offset is within a quarter of the highest we've // seen. This is ok - just assuming some out-of-order // delivery. nonce = decState.nonce usedOffsets = decState.usedOffsets } else if highestOffsetSeen < (1<<13) && offsetNoFlags > ((1<<14)+(1<<13)) && (offsetNoFlags-highestOffsetSeen) > ((1<<14)+(1<<13)) { // offset is in the last quarter, highestOffsetSeen is in // the first quarter, and offset is under a quarter behind // us. This is ok - as above, just some out of order. But // here it means we're dealing with the previous nonce nonce = decState.previousNonce usedOffsets = decState.previousUsedOffsets } else { return nil, fmt.Errorf("Unexpected offset when decrypting UDP packet") } } offsetNoFlagsInt := int(offsetNoFlags) if usedOffsets.Contains(offsetNoFlagsInt) { return nil, fmt.Errorf("Suspected replay attack detected when decrypting UDP packet") } SetNonceLow15Bits(nonce, offsetNoFlags) result, success := secretbox.Open(nil, buf[2:], nonce, nd.conn.SessionKey) if success { usedOffsets.Add(offsetNoFlagsInt) return result, nil } else { return nil, fmt.Errorf("Unable to decrypt msg via UDP: %v", buf) } }