shadow1ng/fscan · error

unexpected oracle packet type %d

Error message

unexpected oracle packet type %d

What it means

When the TNS session receives a packet whose type is not Accept, Refuse, or Redirect, connect reports it via 'unexpected oracle packet type %d'. The raw protocol layer only understands these three response types during connection setup, so anything else means the peer is not behaving like an Oracle listener.

Source

Thrown at plugins/services/oracle_raw.go:216

		if s.version >= 315 {
			s.sessionDataUnit = binary.BigEndian.Uint32(p.raw[32:36])
			s.transportDataUnit = binary.BigEndian.Uint32(p.raw[36:40])
		}
		if s.transportDataUnit < s.sessionDataUnit {
			s.sessionDataUnit = s.transportDataUnit
		}
		s.acfl0 = p.raw[22]
		s.acfl1 = p.raw[23]
		if s.version >= 315 {
			s.handshakeComplete = true
		}
		return nil
	case oraclePacketRefuse:
		return oracleRefuseError(p.raw)
	case oraclePacketRedirect:
		return errors.New("oracle redirect is not supported by lightweight auth")
	default:
		return fmt.Errorf("unexpected oracle packet type %d", p.typ)
	}
}

func oracleConnectData(host string, port int, serviceName string) string {
	address := fmt.Sprintf("(ADDRESS=(PROTOCOL=tcp)(HOST=%s)(PORT=%d))", host, port)
	connectData := "(CONNECT_DATA=(SERVICE_NAME=" + serviceName + "))"
	return "(DESCRIPTION=" + address + connectData + ")"
}

type oraclePacket struct {
	typ  uint8
	flag uint8
	raw  []byte
	data []byte
}

func (s *oracleSession) readPacket() (*oraclePacket, error) {
	header := make([]byte, 8)

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify the target actually runs an Oracle listener on that port
  2. Check for port forwarding/proxy that injects non-TNS bytes
  3. Re-sync the parser — ensure prior reads consumed exactly the packet length (see invalid oracle packet length handling)
  4. Add the unknown type's numeric value to diagnostics when reporting

Example fix

// before
default:
    return fmt.Errorf("unexpected oracle packet type %d", p.typ)
// after
default:
    return fmt.Errorf("unexpected oracle packet type %d (raw % x)", p.typ, p.raw)
Defensive patterns

Strategy: validation

Validate before calling

// pre-verify the port speaks TNS before protocol work
tn, err := net.DialTimeout("tcp", addr, 3*time.Second)
if err != nil { return err }
// optionally send an empty TNS probe and check for a recognizable reply

Type guard

func isKnownOraclePacket(typ byte) bool {
    return typ == oraclePacketAccept || typ == oraclePacketRefuse || typ == oraclePacketRedirect
}

Try / catch

if err := s.connect(ctx, host, port, svc); err != nil {
    if strings.Contains(err.Error(), "unexpected oracle packet type") {
        return ErrNotOracleListener // classify target as non-Oracle, skip
    }
    return err
}

Prevention

When it happens

Trigger: oracleRawAuth -> connect reads a packet after sending the TNS CONNECT data and its type byte is outside the known set (oraclePacketAccept/Refuse/Redirect).

Common situations: Target port is not Oracle (HTTP or SSH server echoing bytes); a proxy answers with its own protocol; corrupt stream desynchronizes packet framing so a payload byte is read as a type.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/a43226817ce8cf84. Report an issue: GitHub.