Example #1
0
// stateFinWait2 handles packets for the FIN-WAIT-2 state
func (c *Connection) stateFinWait2(p *types.PacketManifest, flow *types.TcpIpFlow, nextSeqPtr *types.Sequence, nextAckPtr *types.Sequence, statePtr *uint8) {
	c.detectCensorInjection(p)
	diff := nextSeqPtr.Difference(types.Sequence(p.TCP.Seq))
	if diff < 0 {
		// overlap
		if len(p.Payload) > 0 {
			c.detectInjection(p, p.Flow)
		}
	} else if diff > 0 {
		// future out of order
		log.Print("FIN-WAIT-2: out of order packet received.\n")
		log.Printf("got TCP.Seq %d expected %d\n", p.TCP.Seq, *nextSeqPtr)
		c.Close()
	} else if diff == 0 {
		// contiguous
		if p.TCP.ACK && p.TCP.FIN {
			if types.Sequence(p.TCP.Ack).Difference(*nextAckPtr) != 0 {
				log.Print("FIN-WAIT-2: out of order ACK packet received.\n")
				c.Close()
				return
			}
			*nextSeqPtr += 1
			*statePtr = TCP_TIME_WAIT
		} else {
			if len(p.Payload) > 0 {
				c.detectInjection(p, p.Flow)
			} else {
				log.Print("FIN-WAIT-2: wtf non-FIN/ACK with payload len 0")
			}
		}
	}
}
// addContiguous adds contiguous byte-sets to a connection.
// returns the next Sequence number and a bool value set to
// true if the end of connection was detected.
func (o *OrderedCoalesce) addContiguous(nextSeq types.Sequence) (types.Sequence, bool) {
	var isEnd bool
	for o.first != nil && nextSeq.Difference(o.first.Seq) <= 0 {
		nextSeq, isEnd = o.addNext(nextSeq)
		if isEnd {
			return nextSeq, true
		}
	}
	return nextSeq, false
}
// addNext pops the first page off our doubly-linked-list and
// appends it to the reassembly-ring.
// Here we also handle the case where the connection should be closed
// by returning the bool value set to true.
func (o *OrderedCoalesce) addNext(nextSeq types.Sequence) (types.Sequence, bool) {
	if o.first == nil {
		panic("o.first is nil")
	}
	diff := nextSeq.Difference(o.first.Seq)
	if nextSeq == types.InvalidSequence {
		o.first.Skip = -1
	} else if diff > 0 {
		o.first.Skip = int(diff)
	}
	if o.first.End {
		o.freeNext()
		return -1, true // after closing the connection our Sequence return value doesn't matter
	}
	if len(o.first.Bytes) == 0 {
		o.freeNext()
		return nextSeq, false
	}
	// ensure we do not add segments that end before nextSeq
	diff = o.first.Seq.Add(len(o.first.Bytes)).Difference(nextSeq)
	if diff > 0 {
		o.freeNext()
		return nextSeq, false
	}
	if o.DetectCoalesceInjection && len(o.first.Bytes) > 0 {
		// XXX stream segment overlap condition
		if diff < 0 {
			p := types.PacketManifest{
				Timestamp: o.first.Seen,
				Payload:   o.first.Bytes,
				TCP: layers.TCP{
					Seq: uint32(o.first.Seq),
				},
			}
			event := injectionInStreamRing(&p, o.Flow, o.StreamRing, "coalesce injection", 0)
			if event != nil {
				o.log.Log(event)
			} else {
				log.Print("not an attack attempt; a normal TCP unordered stream segment coalesce\n")
			}
		}
	}
	bytes, seq := byteSpan(nextSeq, o.first.Seq, o.first.Bytes) // XXX injection happens here
	if bytes != nil {
		o.first.Bytes = bytes
		nextSeq = seq
		// append reassembly to the reassembly ring buffer
		if len(o.first.Bytes) > 0 {
			o.StreamRing.Reassembly = &o.first.Reassembly
			o.StreamRing = o.StreamRing.Next()
		}
	}
	o.freeNext()
	return nextSeq, false
}
func byteSpan(expected, received types.Sequence, bytes []byte) (toSend []byte, next types.Sequence) {
	if expected == types.InvalidSequence {
		return bytes, received.Add(len(bytes))
	}
	span := int(received.Difference(expected))
	if span <= 0 {
		return bytes, received.Add(len(bytes))
	} else if len(bytes) < span {
		return nil, expected
	}
	return bytes[span:], expected.Add(len(bytes) - span)
}
Example #5
0
// getHeadFromRing returns a pointer to the oldest ring element that
// contains the beginning of our sequence range (start - end) AND
// whose Reassembly.Skip value is 0 (zero).
func getHeadFromRing(ringPtr *types.Ring, start, end types.Sequence) *types.Ring {
	var head *types.Ring
	current := ringPtr.Prev()
	if current.Reassembly == nil {
		return nil
	}
	if start.Difference(current.Reassembly.Seq.Add(len(current.Reassembly.Bytes)-1)) < 0 {
		log.Printf("lastestSeq %d < newStartSeq %d\n", current.Reassembly.Seq.Add(len(current.Reassembly.Bytes)-1), start)
		return nil
	}
	head = nil
	var candidate *types.Ring = nil

	for current := ringPtr.Prev(); current != ringPtr && current.Reassembly != nil; current = current.Prev() {
		if len(current.Reassembly.Bytes) == 0 {
			continue
		}

		startDiff := current.Reassembly.Seq.Difference(start)
		if startDiff == 0 {
			return current
		}
		if startDiff < 0 {
			finishEndDiff := current.Reassembly.Seq.Difference(end)
			if finishEndDiff >= 0 {
				candidate = current
			}

			continue
		} else {
			endDiff := start.Difference(current.Reassembly.Seq.Add(len(current.Reassembly.Bytes) - 1))
			if endDiff >= 0 {
				head = current
				break
			}
		}
	}
	if head == nil && candidate != nil {
		head = candidate
	}
	return head
}
func TestGetStartSequence(t *testing.T) {
	var start types.Sequence = 4
	var head *types.Ring = types.NewRing(10)
	head.Reassembly = &types.Reassembly{
		Seq:   3,
		Bytes: []byte{1, 2, 3, 4, 5, 6, 7},
	}
	startSeq := getStartSequence(head, start)
	if startSeq.Difference(start) != 0 {
		t.Errorf("startSeq %d != start %d\n", startSeq, start)
		t.Fail()
	}

	start = 2
	startSeq = getStartSequence(head, start)
	if startSeq != start.Add(1) {
		t.Errorf("startSeq %d != start %d\n", startSeq, start.Add(1))
		t.Fail()
	}
}
Example #7
0
// stateFinWait1 handles packets for the FIN-WAIT-1 state
//func (c *Connection) stateFinWait1(p *types.PacketManifest) {
func (c *Connection) stateFinWait1(p *types.PacketManifest, flow *types.TcpIpFlow, nextSeqPtr *types.Sequence, nextAckPtr *types.Sequence, statePtr, otherStatePtr *uint8) {
	c.detectCensorInjection(p)
	diff := nextSeqPtr.Difference(types.Sequence(p.TCP.Seq))
	if diff < 0 {
		// overlap
		if len(p.Payload) > 0 {
			c.detectInjection(p, p.Flow)
		}
		return
	} else if diff > 0 {
		// future out of order
		log.Print("FIN-WAIT-1: ignoring out of order packet")
		return
	} else if p.TCP.ACK {
		*nextAckPtr += 1
		if p.TCP.FIN {
			*statePtr = TCP_CLOSING
			*otherStatePtr = TCP_LAST_ACK
			*nextSeqPtr = types.Sequence(p.TCP.Seq).Add(len(p.Payload) + 1)
			if types.Sequence(p.TCP.Ack).Difference(*nextAckPtr) != 0 {
				log.Printf("FIN-WAIT-1: unexpected ACK: got %d expected %d TCP.Seq %d\n", p.TCP.Ack, *nextAckPtr, p.TCP.Seq)
				c.closingFlow = p.Flow
				c.closingSeq = types.Sequence(p.TCP.Seq)
				return
			}
		} else {
			*statePtr = TCP_FIN_WAIT2
			*nextSeqPtr = types.Sequence(p.TCP.Seq).Add(len(p.Payload))
		}
	} else {
		log.Print("FIN-WAIT-1: non-ACK packet received.\n")
		c.closingFlow = p.Flow
		c.closingSeq = types.Sequence(p.TCP.Seq)
		return
	}
}
Example #8
0
// getOverlapBytes takes several arguments:
// head and tail - ring pointers used to indentify a list of ring elements.
// start and end - sequence numbers representing locations in head and tail respectively.
// NOTE: here we assume that the head and tail were calculated properly such that:
// 1. start must be located within the head segment's sequence boundaries or BEFORE.
// 2. end must be located within the tail segment's sequence boundaries or AFTER.
// normally head and tail values would be procured with a call to getOverlapRings like this:
//	head, tail := getOverlapRings(p, flow, ringPtr)
// Given these arguments, getOverlapBytes returns the overlap byte array;
// that is the contiguous data stored in our ring buffer
// that overlaps with the stream segment specified by the start and end Sequence boundaries.
// The other return values are the slice offsets of the original packet payload that can be used to derive
// the section of the packet that has overlapped with our Reassembly ring buffer.
func getOverlapBytes(head, tail *types.Ring, start, end types.Sequence) ([]byte, int, int) {
	var overlapStartSlice, overlapEndSlice int
	var overlapBytes []byte
	var diff int

	if head == nil || tail == nil {
		panic("wtf; head or tail is nil\n")
	}
	if len(head.Reassembly.Bytes) == 0 {
		panic("length of head ring element is zero")
	}
	if len(tail.Reassembly.Bytes) == 0 {
		panic("length of tail ring element is zero")
	}

	packetLength := start.Difference(end) + 1
	if packetLength <= 0 {
		panic("wtf")
	}
	var headOffset int
	tailLastSeq := tail.Reassembly.Seq.Add(len(tail.Reassembly.Bytes) - 1)
	startDiff := head.Reassembly.Seq.Difference(start)
	if startDiff < 0 {
		headOffset = 0
		overlapStartSlice = -1 * startDiff
		if overlapStartSlice > packetLength {
			// XXX print a error message here or panic?
			log.Print("getOverlapbytes: incorrect start/end head/tail parameters.")
			return nil, 0, 0
		}
	} else if startDiff == 0 {
		headOffset = 0
		overlapStartSlice = 0
	} else {
		headOffset = startDiff
		overlapStartSlice = 0
	}
	if head.Reassembly.Seq == tail.Reassembly.Seq {
		log.Print("head == tail\n")
		var endOffset int
		diff = tailLastSeq.Difference(end)
		if diff <= 0 {
			overlapEndSlice = packetLength
			tailDiff := end.Difference(tailLastSeq)
			endOffset = len(head.Reassembly.Bytes) - tailDiff
		} else {
			overlapEndSlice = packetLength - diff
			endOffset = len(head.Reassembly.Bytes)
		}
		overlapBytes = head.Reassembly.Bytes[headOffset:endOffset]
	} else {
		log.Print("head != tail\n")
		diff = tailLastSeq.Difference(end)
		var tailSlice int
		// if end is equal or less than tailLastSeq
		if diff <= 0 {
			overlapEndSlice = packetLength
			tailSlice = len(tail.Reassembly.Bytes) - (diff * -1)
			if tailSlice < 0 {
				panic("regression in getTailFromRing")
			}
		} else {
			if diff > packetLength {
				// XXX should we opt out instead of making the comparison?
				overlapEndSlice = packetLength
			} else {
				overlapEndSlice = packetLength - diff
				if overlapEndSlice < overlapStartSlice {
					// XXX wtf
					return nil, 0, 0
				}
			}
			tailSlice = len(tail.Reassembly.Bytes)
		}
		overlapBytes = getRingSlice(head, tail, headOffset, tailSlice)
		if overlapBytes == nil {
			return nil, 0, 0
		}
	}
	return overlapBytes, overlapStartSlice, overlapEndSlice
}