cleanup; fewer panics/less panic; package docs; remove unused code

This commit is contained in:
Justin Bastress 2018-02-28 15:42:03 -05:00
parent 96b0680173
commit 67a4af48f7
4 changed files with 57 additions and 94 deletions

@ -243,7 +243,7 @@ func (conn *Connection) Connect(connectDescriptor string) (*HandshakeLog, error)
nsnRequest := &TNSData{
DataFlags: 0,
Data: (&TNSDataNSN{
ID: 0xdeadbeef,
ID: DataIDNSN,
Version: encodeReleaseVersion(conn.scanner.config.ReleaseVersion),
Options: NSNOptions(0),
Services: []NSNService{

@ -1,5 +1,24 @@
// Package oracle provides a zgrab2 module that proves for oracle.
// TODO: Describe module, the flags, the probe, the output, etc.
// Package oracle provides the zgrab2 scanner module for Oracle's TNS protocol.
// Default Port: 1521 (TCP)
//
// The scan does the first part of a TNS handshake, prior to the point where
// any actual authentication is required; the happy case goes
// -> Connect(--client-version, --min-server-version, --connect-descriptor)
// <- Resend
// -> Connect(exact same data)
// <- Accept(server_version)
// -> Data: Native Service Negotiation
// <- Data: Native Service Negotiation(component release versions)
//
// The default scan uses a generic connect descriptor with no explicit connect
// data / service name, so it relies on the server to choose the destination.
//
// Sending an intentionally invalid --connect-descriptor can force a Refuse
// response, which should include a version number.
//
// The output includes the server's protocol version and any component release
// versions that are returned.
package oracle
import (

@ -177,8 +177,11 @@ func (driver *TNSDriver) EncodePacket(packet *TNSPacket) ([]byte, error) {
packet.Header.Length = uint32(len(body) + 8)
}
}
header := packet.Header.Encode()
return append(header, body...), nil
if header, err := packet.Header.Encode(); err != nil {
return nil, err
} else {
return append(header, body...), nil
}
}
// TNSFlags is the type for the TNS header's flags.
@ -186,6 +189,7 @@ type TNSFlags uint8
// TNSHeader is the 8-byte header that precedes all TNS packets.
type TNSHeader struct {
// mode used for encoding / decoding this packet.
mode TNSMode
// Length is the big-endian length of the entire packet, including the 8
@ -208,13 +212,13 @@ type TNSHeader struct {
}
// Encode returns the encoded TNSHeader.
func (header *TNSHeader) Encode() []byte {
func (header *TNSHeader) Encode() ([]byte, error) {
ret := make([]byte, 8)
next := outputBuffer(ret)
switch header.mode {
case TNSModeOld:
if header.Length > 0xffff {
panic(ErrInvalidData)
return nil, ErrInvalidInput
}
next.pushU16(uint16(header.Length))
next.pushU16(header.PacketChecksum)
@ -227,9 +231,9 @@ func (header *TNSHeader) Encode() []byte {
next.pushU8(byte(header.Flags))
next.pushU16(header.HeaderChecksum)
default:
panic(fmt.Errorf("Bad TNSDriver mode 0x%x", header.mode))
return nil, ErrInvalidInput
}
return ret
return ret, nil
}
// ReadTNSHeader reads/decodes a TNSHeader from the first 8 bytes of the stream.
@ -631,23 +635,6 @@ func (reader *chainedReader) Read(buf []byte) (int, error) {
return n, err
}
// readError is a special error type to distinguish read errors (which should be
// converted to a return value) from other panics.
type readError error
// Helper to convert readErrors into return values.
func unpanic() error {
if rerr := recover(); rerr != nil {
switch err := rerr.(type) {
case readError:
return err
default:
panic(rerr)
}
}
return nil
}
// ReadTNSConnect reads a TNSConnect packet from the reader, which should point
// to the first byte after the end of the TNSHeader.
func ReadTNSConnect(reader io.Reader, header *TNSHeader) (*TNSConnect, error) {
@ -777,33 +764,6 @@ func (packet *TNSAccept) GetType() PacketType {
return PacketTypeAccept
}
func readU8(reader io.Reader) uint8 {
buf := make([]byte, 1)
_, err := io.ReadFull(reader, buf)
if err != nil {
panic(readError(err))
}
return buf[0]
}
func readU16(reader io.Reader) uint16 {
buf := make([]byte, 2)
_, err := io.ReadFull(reader, buf)
if err != nil {
panic(readError(err))
}
return binary.BigEndian.Uint16(buf)
}
func readU32(reader io.Reader) uint32 {
buf := make([]byte, 4)
_, err := io.ReadFull(reader, buf)
if err != nil {
panic(readError(err))
}
return binary.BigEndian.Uint32(buf)
}
// ReadTNSAccept reads a TNSAccept packet body from the stream. reader should
// point to the first byte after the TNSHeader.
func ReadTNSAccept(reader io.Reader, header *TNSHeader) (*TNSAccept, error) {
@ -836,8 +796,8 @@ func (reason RefuseReason) String() string {
return fmt.Sprintf("0x%02x", uint8(reason))
}
// TNSRefuse is returned by the server when (...TODO: details -- not returned on
// failed auth from TNSConnect).
// TNSRefuse is returned by the server when an error occurs (for instance, an
// invalid connect descriptor).
type TNSRefuse struct {
// TODO: details
AppReason RefuseReason
@ -1184,22 +1144,29 @@ func ReadNSNService(reader io.Reader, ret *NSNService) (*NSNService, error) {
if ret == nil {
ret = &NSNService{}
}
ret.Type = NSNServiceType(readU16(reader))
n := int(readU16(reader))
next := startReading(reader)
next.read(&ret.Type)
n, err := next.readU16()
if err != nil {
return nil, err
}
if n > 0x0400 {
// Arbitrary but sufficiently huge cut off. Typical values are single
// digits. The total encoded size must fit into 16 bits.
return nil, ErrInvalidData
}
ret.Marker = readU32(reader)
next.read(&ret.Marker)
// Check if Marker == 0?
ret.Values = make([]NSNValue, n)
for i := 0; i < n; i++ {
ret.Values = make([]NSNValue, int(n))
for i := 0; i < int(n); i++ {
_, err := ReadNSNValue(reader, &ret.Values[i])
if err != nil {
return nil, err
}
}
if err := next.Error(); err != nil {
return nil, err
}
return ret, nil
}
@ -1365,15 +1332,15 @@ func ReadNSNValue(reader io.Reader, ret *NSNValue) (*NSNValue, error) {
if ret == nil {
ret = &NSNValue{}
}
size := readU16(reader)
ret.Type = NSNValueType(readU16(reader))
ret.Value = make([]byte, size)
n, err := reader.Read(ret.Value)
next := startReading(reader)
size, err := next.readU16()
if err != nil {
return nil, err
}
if n != len(ret.Value) {
return nil, ErrInvalidData
next.read(&ret.Type)
next.readNew(&ret.Value, int(size))
if err := next.Error(); err != nil {
return nil, err
}
return ret, nil
}
@ -1513,32 +1480,6 @@ type TNSPacket struct {
Body TNSPacketBody
}
// Encode the packet (header + body). If header is nil, create one with no flags
// and the type set to the body's type. If header.Length == 0, set it to the
// appropriate value (length of encoded body + 8).
func (packet *TNSPacket) oldEncode() []byte {
body := packet.Body.Encode()
if packet.Header == nil {
packet.Header = &TNSHeader{
Length: 0,
PacketChecksum: 0,
Type: packet.Body.GetType(),
// Flags -- aka Reserved Byte -- is "04" in some Connect packets?
Flags: 0,
HeaderChecksum: 0,
}
}
if packet.Header.Length == 0 {
if len(body)+8 > 0xffff {
panic(fmt.Errorf("Body too large to fit into 16-bit length (%d bytes)", len(body)))
}
// It is up to the user to check the body length for overflows before calling Encode
packet.Header.Length = uint32(len(body) + 8)
}
header := packet.Header.Encode()
return append(header, body...)
}
// ReadTNSPacket reads a TNSPacket from the stream, or returns nil + an error
// if one cannot be read.
func (driver *TNSDriver) ReadTNSPacket(reader io.Reader) (*TNSPacket, error) {

@ -143,7 +143,7 @@ var validTNSData = map[string]TestCase{
Body: &TNSData{
DataFlags: 0,
Data: (&TNSDataNSN{
ID: 0xdeadbeef,
ID: DataIDNSN,
Version: encodeReleaseVersion("10.2.0.3.0"),
Options: NSNOptions(0),
Services: []NSNService{
@ -463,7 +463,10 @@ func TestTNSHeaderEncode(t *testing.T) {
driver := getTNSDriver()
for hex, header := range validHeaders {
bin := fromHex(hex)
encoded := header.Encode()
encoded, err := header.Encode()
if err != nil {
t.Fatalf("TNSHeader.Encode error: %v", err)
}
if !bytes.Equal(bin, encoded) {
t.Errorf("TNSHeader.Encode mismatch:[\n%s\n]", interleave(bin, encoded))
}