{"record":{"id":"60820258968545cf","repo":"shadow1ng/fscan","slug":"oracle-protocol-negotiation-expected-message-1-go","errorCode":null,"errorMessage":"oracle protocol negotiation expected message 1, got %d","messagePattern":"oracle protocol negotiation expected message 1, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/oracle_raw.go","lineNumber":969,"sourceCode":"\tif length > 0 {\n\t\t_, err = s.getBytes(length)\n\t}\n\treturn err\n}\n\nfunc (s *oracleSession) protocolNegotiation() (*oracleTCPNego, error) {\n\ts.reset()\n\ts.putBytes(1, 6, 0)\n\ts.putBytes([]byte(\"OracleClientGo\\x00\")...)\n\tif err := s.writeData(); err != nil {\n\t\treturn nil, err\n\t}\n\tmsg, err := s.getByte()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif msg != 1 {\n\t\treturn nil, fmt.Errorf(\"oracle protocol negotiation expected message 1, got %d\", msg)\n\t}\n\tproto, err := s.getByte()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif proto != 4 && proto != 5 && proto != 6 {\n\t\treturn nil, errors.New(\"unsupported oracle server protocol version\")\n\t}\n\tif _, err = s.getByte(); err != nil {\n\t\treturn nil, err\n\t}\n\tif _, err = s.getNullTermString(50); err != nil {\n\t\treturn nil, err\n\t}\n\tserverCharset, err := s.getInt(2, false, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":951,"sourceCodeEnd":987,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/oracle_raw.go#L951-L987","documentation":"After the connect packet is sent, the Oracle raw protocol handshake expects the server's first protocol negotiation message to start with message type 1. The server sent a different message byte, so the library aborts with the actual value received. This is a guard against talking to something that is not a normal Oracle TNS listener response flow.","triggerScenarios":"oracleRawAuth -> protocolNegotiation reads the first byte after connecting and it is not 1 (e.g. 4 = a redirect/refuse packet, an error packet, or garbage from a non-Oracle service).","commonSituations":"Connecting to a port that is not an Oracle listener (wrong host/port config); the listener redirects to another node and the client mishandles the redirect; an old Oracle version or intermediary device answering with a different message order; a health-check probe hitting the DB port.","solutions":["Verify the host/port/SID or service name in the connection string points at a real Oracle listener (test with tnsping or lsnrctl status).","Check whether the listener redirects connections (LOAD_BALANCE/PRECONNECT options) and connect directly to the serving node if redirects are not supported.","Confirm no firewall/proxy is interposing on the connection; capture the first response bytes to see what the server actually returned."],"exampleFix":"// before\nds := \"oracle://user:pass@dbhost:1522/SVC\"\n// after (correct listener port verified via lsnrctl status)\nds := \"oracle://user:pass@dbhost:1521/SVC\"","handlingStrategy":"validation","validationCode":"// Pre-flight: confirm a live Oracle listener before opening the app connection\nconn, err := net.DialTimeout(\"tcp\", \"dbhost:1521\", 3*time.Second)\nif err != nil { log.Fatal(\"no listener on port\") }\nconn.Close()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate host/port/service in DSNs against lsnrctl status output","Avoid connecting to ports shared with other services","Handle listener redirects by connecting to the actual serving node"],"tags":["oracle","protocol","handshake","connection"],"backgroundTag":"unexpected-response-shape","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}