shadow1ng/fscan · error

unsupported oracle server protocol version

Error message

unsupported oracle server protocol version

What it means

After sending the connect (SDU/protocol) request, the server replies with its native protocol version byte. This library only implements versions 4, 5 and 6 of the Oracle Net handshake; any other value means the speaking peer is incompatible and the client aborts before authentication.

Source

Thrown at plugins/services/oracle_raw.go:976

	s.reset()
	s.putBytes(1, 6, 0)
	s.putBytes([]byte("OracleClientGo\x00")...)
	if err := s.writeData(); err != nil {
		return nil, err
	}
	msg, err := s.getByte()
	if err != nil {
		return nil, err
	}
	if msg != 1 {
		return nil, fmt.Errorf("oracle protocol negotiation expected message 1, got %d", msg)
	}
	proto, err := s.getByte()
	if err != nil {
		return nil, err
	}
	if proto != 4 && proto != 5 && proto != 6 {
		return nil, errors.New("unsupported oracle server protocol version")
	}
	if _, err = s.getByte(); err != nil {
		return nil, err
	}
	if _, err = s.getNullTermString(50); err != nil {
		return nil, err
	}
	serverCharset, err := s.getInt(2, false, false)
	if err != nil {
		return nil, err
	}
	serverFlags, err := s.getByte()
	if err != nil {
		return nil, err
	}
	charsetElem, err := s.getInt(2, false, false)
	if err != nil {
		return nil, err

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify the DSN host/port targets the Oracle TNS listener (tnsping-style check), not another service
  2. Check the listener log and connect string (SERVICE_NAME/SID) for rejection causes that make the server return an error byte
  3. Confirm the target Oracle server version is one the plugin supports (protocol 4-6)
  4. If behind a proxy, ensure it passes TNS traffic unmodified

Example fix

// before
if proto != 4 && proto != 5 && proto != 6 {
	return nil, errors.New("unsupported oracle server protocol version")
}
// after
if proto != 4 && proto != 5 && proto != 6 {
	return nil, fmt.Errorf("unsupported oracle server protocol version: %d", proto)
}
Defensive patterns

Strategy: validation

Validate before calling

// verify the endpoint is an Oracle listener before auth
conn, err := net.DialTimeout("tcp", host+":"+port, 5*time.Second)
if err != nil { return err }
// wrong service usually returns a non-4/5/6 version byte immediately
conn.Close()

Type guard

func isSupportedProtocolVersion(b byte) bool { return b == 4 || b == 5 || b == 6 }

Try / catch

if err != nil && strings.Contains(err.Error(), "unsupported oracle server protocol version") {
	return fmt.Errorf("check DSN host/port points to an Oracle TNS listener and server version is supported: %w", err)
}

Prevention

When it happens

Trigger: protocolNegotiation() reads the version byte via s.getByte() during oracleRawAuth and it is not 4, 5 or 6 (e.g. 0xff rejection marker or an unexpected version).

Common situations: Listener rejecting the connect string (returns an error marker instead of a version byte); connecting through the wrong port (e.g. a non-Oracle service); extremely old/new server whose initial version byte differs.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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