Esempio n. 1
0
func isSpecialPgsqlCommand(data []byte) (bool, int, int) {

	if len(data) < 8 {
		// 8 bytes required
		return false, 0, 0
	}

	// read length
	length := readLength(data[0:])

	// read command identifier
	code := int(common.BytesNtohl(data[4:]))

	if length == 16 && code == 80877102 {
		// Cancel Request
		logp.Debug("pgsqldetailed", "Cancel Request, length=%d", length)
		return true, length, cancelRequest
	} else if length == 8 && code == 80877103 {
		// SSL Request
		logp.Debug("pgsqldetailed", "SSL Request, length=%d", length)
		return true, length, sslRequest
	} else if code == 196608 {
		// Startup Message
		logp.Debug("pgsqldetailed", "Startup Message, length=%d", length)
		return true, length, startupMessage
	}
	return false, 0, 0
}
Esempio n. 2
0
func (thrift *thriftPlugin) readI32(data []byte) (value string, ok bool, complete bool, off int) {
	if len(data) < 4 {
		return "", true, false, 0
	}
	i32 := common.BytesNtohl(data[:4])
	value = strconv.Itoa(int(i32))

	return value, true, true, 4
}
Esempio n. 3
0
func (thrift *thriftPlugin) readMap(data []byte) (value string, ok bool, complete bool, off int) {
	if len(data) < 6 {
		return "", true, false, 0
	}
	typeKey := data[0]
	typeValue := data[1]

	funcReaderKey, typeFound := thrift.funcReadersByType(typeKey)
	if !typeFound {
		logp.Debug("thrift", "Field type %d not known", typeKey)
		return "", false, false, 0
	}

	funcReaderValue, typeFound := thrift.funcReadersByType(typeValue)
	if !typeFound {
		logp.Debug("thrift", "Field type %d not known", typeValue)
		return "", false, false, 0
	}

	sz := int(common.BytesNtohl(data[2:6]))
	if sz < 0 {
		logp.Debug("thrift", "Map too big: %d", sz)
		return "", false, false, 0
	}

	fields := []string{}
	offset := 6

	for i := 0; i < sz; i++ {
		key, ok, complete, bytesRead := funcReaderKey(data[offset:])
		if !ok {
			return "", false, false, 0
		}
		if !complete {
			return "", true, false, 0
		}
		offset += bytesRead

		value, ok, complete, bytesRead := funcReaderValue(data[offset:])
		if !ok {
			return "", false, false, 0
		}
		if !complete {
			return "", true, false, 0
		}
		offset += bytesRead

		if i < thrift.collectionMaxSize {
			fields = append(fields, key+": "+value)
		} else if i == thrift.collectionMaxSize {
			fields = append(fields, "...")
		}
	}

	return "{" + strings.Join(fields, ", ") + "}", true, true, offset
}
Esempio n. 4
0
// Parse 32bit binary value from the buffer at index. Will not advance the read
// buffer
func (b *Buffer) ReadNetUint32At(index int) (uint32, error) {
	if b.Failed() {
		return 0, b.err
	}
	if !b.Avail(4 + index) {
		return 0, b.bufferEndError()
	}
	return common.BytesNtohl(b.data[index+b.mark:]), nil

}
Esempio n. 5
0
// Parse 32bit binary value in network byte order from Buffer
// (converted to Host order).
func (b *Buffer) ReadNetUint32() (uint32, error) {
	if b.Failed() {
		return 0, b.err
	}
	tmp := b.data[b.mark:]
	if err := b.Advance(4); err != nil {
		return 0, err
	}
	value := common.BytesNtohl(tmp)
	return value, nil
}
Esempio n. 6
0
// Common implementation for lists and sets (they share the same binary repr).
func (thrift *thriftPlugin) readListOrSet(data []byte) (value string, ok bool, complete bool, off int) {
	if len(data) < 5 {
		return "", true, false, 0
	}
	typ := data[0]

	funcReader, typeFound := thrift.funcReadersByType(typ)
	if !typeFound {
		logp.Debug("thrift", "Field type %d not known", typ)
		return "", false, false, 0
	}

	sz := int(common.BytesNtohl(data[1:5]))
	if sz < 0 {
		logp.Debug("thrift", "List/Set too big: %d", sz)
		return "", false, false, 0
	}

	fields := []string{}
	offset := 5

	for i := 0; i < sz; i++ {
		value, ok, complete, bytesRead := funcReader(data[offset:])
		if !ok {
			return "", false, false, 0
		}
		if !complete {
			return "", true, false, 0
		}

		if i < thrift.collectionMaxSize {
			fields = append(fields, value)
		} else if i == thrift.collectionMaxSize {
			fields = append(fields, "...")
		}
		offset += bytesRead
	}

	return strings.Join(fields, ", "), true, true, offset
}
Esempio n. 7
0
// thriftReadString caps the returned value to ThriftStringMaxSize but returns the
// off to the end of it.
func (thrift *thriftPlugin) readString(data []byte) (value string, ok bool, complete bool, off int) {
	if len(data) < 4 {
		return "", true, false, 0 // ok, not complete
	}
	sz := int(common.BytesNtohl(data[:4]))
	if int32(sz) < 0 {
		return "", false, false, 0 // not ok
	}
	if len(data[4:]) < sz {
		return "", true, false, 0 // ok, not complete
	}

	if sz > thrift.stringMaxSize {
		value = string(data[4 : 4+thrift.stringMaxSize])
		value += "..."
	} else {
		value = string(data[4 : 4+sz])
	}
	off = 4 + sz

	return value, true, true, off // all good
}
Esempio n. 8
0
func (thrift *thriftPlugin) messageParser(s *thriftStream) (bool, bool) {
	var ok, complete bool
	var m = s.message

	logp.Debug("thriftdetailed", "messageParser called parseState=%v offset=%v",
		s.parseState, s.parseOffset)

	for s.parseOffset < len(s.data) {
		switch s.parseState {
		case thriftStartState:
			m.start = s.parseOffset
			if thrift.TransportType == thriftTFramed {
				// read I32
				if len(s.data) < 4 {
					return true, false
				}
				m.frameSize = common.BytesNtohl(s.data[:4])
				s.parseOffset = 4
			}

			ok, complete = thrift.readMessageBegin(s)
			logp.Debug("thriftdetailed", "readMessageBegin returned: %v %v", ok, complete)
			if !ok {
				return false, false
			}
			if !complete {
				return true, false
			}

			if !m.isRequest && !thrift.captureReply {
				// don't actually read the result
				logp.Debug("thrift", "Don't capture reply")
				m.returnValue = ""
				m.exceptions = ""
				return true, true
			}
			s.parseState = thriftFieldState
		case thriftFieldState:
			ok, complete, field := thrift.readField(s)
			logp.Debug("thriftdetailed", "readField returned: %v %v", ok, complete)
			if !ok {
				return false, false
			}
			if complete {
				// done
				var method *thriftIdlMethod
				if thrift.idl != nil {
					method = thrift.idl.findMethod(m.method)
				}
				if m.isRequest {
					if method != nil {
						m.params = thrift.formatStruct(m.fields, true, method.params)

						m.service = method.service.Name
					} else {
						m.params = thrift.formatStruct(m.fields, false, nil)
					}
				} else {
					if len(m.fields) > 1 {
						logp.Warn("Thrift RPC response with more than field. Ignoring all but first")
					}
					if len(m.fields) > 0 {
						field := m.fields[0]
						if field.id == 0 {
							m.returnValue = field.value
							m.exceptions = ""
						} else {
							m.returnValue = ""
							if method != nil {
								m.exceptions = thrift.formatStruct(m.fields, true, method.exceptions)
							} else {
								m.exceptions = thrift.formatStruct(m.fields, false, nil)
							}
							m.hasException = true
						}
					}
				}
				return true, true
			}
			if field == nil {
				return true, false // ok, not complete
			}

			m.fields = append(m.fields, *field)
		}
	}

	return true, false
}
Esempio n. 9
0
func (thrift *thriftPlugin) readMessageBegin(s *thriftStream) (bool, bool) {
	var ok, complete bool
	var offset, off int

	m := s.message

	if len(s.data[s.parseOffset:]) < 9 {
		return true, false // ok, not complete
	}

	sz := common.BytesNtohl(s.data[s.parseOffset : s.parseOffset+4])
	if int32(sz) < 0 {
		m.version = sz & thriftVersionMask
		if m.version != thriftVersion1 {
			logp.Debug("thrift", "Unexpected version: %d", m.version)
		}

		logp.Debug("thriftdetailed", "version = %d", m.version)

		offset = s.parseOffset + 4

		logp.Debug("thriftdetailed", "offset = %d", offset)

		m.Type = sz & ThriftTypeMask
		m.method, ok, complete, off = thrift.readString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			logp.Debug("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		logp.Debug("thriftdetailed", "method = %s", m.method)
		logp.Debug("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 4 {
			logp.Debug("thriftdetailed", "Less then 4 bytes remaining")
			return true, false // ok, not complete
		}
		m.seqID = common.BytesNtohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	} else {
		// no version mode
		offset = s.parseOffset

		m.method, ok, complete, off = thrift.readString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			logp.Debug("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		logp.Debug("thriftdetailed", "method = %s", m.method)
		logp.Debug("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 5 {
			return true, false // ok, not complete
		}

		m.Type = uint32(s.data[offset])
		offset++
		m.seqID = common.BytesNtohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	}

	if m.Type == ThriftMsgTypeCall || m.Type == ThriftMsgTypeOneway {
		m.isRequest = true
	} else {
		m.isRequest = false
	}

	return true, true
}
Esempio n. 10
0
// length field in pgsql counts total length of length field + payload, not
// including the message identifier. => Always check buffer size >= length + 1
func readLength(b []byte) int {
	return int(common.BytesNtohl(b))
}