informix-db/docs/JDBC_NOTES.md
Ryan Malloy 1a149074d4 Phase 0: populate PROTOCOL_NOTES and JDBC_NOTES from clean-room JDBC reading
Decompiled ifxjdbc.jar (4.50.JC10, build 146, 2023-03-07) with CFR 0.152
into build/jdbc-src/. The decompiled tree is gitignored — it's a
clean-room understanding reference, not shipped code.

Findings landed in two artifacts:

JDBC_NOTES.md — the reverse-lookup index:
- JAR identity (SHA256, manifest, line counts)
- Package layout (com.informix.{asf,jdbc,lang} are the load-bearing
  packages; org.bson and the JDBC API surface get ignored)
- Class index mapping each wire-protocol concern to the responsible
  Java class. Highlights:
  - com.informix.asf.Connection (the wire transport / login PDU)
  - com.informix.asf.IfxData{Input,Output}Stream (framing primitives)
  - com.informix.jdbc.IfxMessageTypes (140+ message-tag constants)
  - com.informix.lang.JavaToIfxType / IfxToJavaType (codecs)
  - com.informix.jdbc.IfxSqli / IfxSqliConnect (the SQLI state machine)
- Auth landscape: plain-password is inline in the binary login PDU;
  PAM is a server-initiated post-login challenge/response; CSM is
  removed from this driver (literally throws an error if you try)

PROTOCOL_NOTES.md — the byte-level wire-format reference:
- Endianness: big-endian, network byte order (confirmed from
  JavaToIfxInt source)
- Width table: SmallInt 2B, Int 4B, BigInt 8B, plus the legacy 10-byte
  LongInt that we skip for MVP
- 16-bit alignment requirement for variable-length payloads — every
  string/decimal/datetime is 0-padded if odd-length, missing this
  desynchronizes the parser
- Login PDU structure decoded byte-by-byte from encodeAscBinary():
  SLheader (6 bytes) + PFheader with markers 100/101/104/106/107/
  108/116/127, capability bitfield, env vars, process info, app name
- Disconnection: bare [short SQ_EXIT=56] both directions, no header
- Post-login messages have NO header — protocol is stream-oriented:
  [short tag][payload][short tag][payload]...
- Message-type tag table categorized by purpose
- Open questions list and cross-check matrix tracking what's
  JDBC-derived vs PCAP-confirmed

DECISION_LOG.md additions:
- ifxjdbc.jar 4.50.JC10 selected as JDBC reference; CFR 0.152 as decompiler
- CSM is officially dead — never plan for it
- Plain-password auth is single-round-trip (no challenge/response)
- Wire-framing primitives locked in for _protocol.py
- Container credentials: user=informix, password=in4mix, on port 9088,
  TLS off

Phase 0 exit gate: criteria #1 (login layout), #2 (message-type tags),
#3 (SELECT 1 hypothesis) are derived from JDBC. PCAP capture (task #7)
and cross-reference (task #2) remaining to corroborate.
2026-05-02 16:00:30 -06:00

13 KiB

IBM JDBC Driver — Wire Protocol Class Index

Phase 0 spike artifact. Reverse-lookup index into the decompiled IBM Informix JDBC driver. This document tells us which Java class to read when we want to understand how the JDBC driver implements a given wire-protocol concern.

Legal note: the decompiled source lives in build/jdbc-src/ and is not committed to this repository. It is consulted as a clean-room understanding reference only. The Python implementation in src/informix_db/ is written from PROTOCOL_NOTES.md (which cites both the observed packet bytes and the JDBC class+method that emits them), never copied from the Java source.


JAR identity

Field Value
Source /home/rpm/bingham/rtmt/lib/ifxjdbc.jar (user-provided; an IBM tooling/RTMT install)
Working copy build/ifxjdbc.jar
SHA256 dc5622cb4e95678d15836b684b6ef1783d37bc0cdd2725208577fc300df4e5f1
Implementation-Title Informix JDBC Driver
Implementation-Version 4.50.10-SNAPSHOT
Build-Date 2023-03-07T11:30:44-0600
Build-Number 146
Main-Class com.informix.jdbc.Version (printable: "IBM Informix JDBC Driver Version 4.50.JC10")
Total entries 685 (.class files)
Decompiled .java files 478

Decompilation

java -jar build/tools/cfr.jar build/ifxjdbc.jar --outputdir build/jdbc-src/ --silent

CFR version: 0.152 (May 2024). Downloaded from https://github.com/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar.


Top-level package layout

com.informix.asf            # wire-transport layer (sockets, framing primitives, SSL, HTTP-tunnel)
com.informix.jdbc           # JDBC API surface: Driver, Connection, Statement, ResultSet, type wrappers
com.informix.jdbc.types     # JDBC type-wrapper sub-types
com.informix.jdbc.udt       # User-defined type support
com.informix.jdbcx          # XA / DataSource / ConnectionPool extensions
com.informix.jns            # Java Naming Service (sqlhosts lookup)
com.informix.judr           # Java User-Defined Routines
com.informix.lang           # Encoding/decoding bridge between Java types and Informix wire types
com.informix.smartTrigger   # Smart-trigger event subscription
com.informix.types          # Informix-side type system (Interval, Decimal, etc.)
com.informix.util           # Tracing, error messages, properties
org.bson.*                  # MongoDB BSON support — ignore for SQLI work

For SQLI wire-protocol implementation, only com.informix.asf, com.informix.jdbc (selected files), com.informix.lang, and com.informix.util.IfxErrMsg matter. Everything else is JDBC API surface, ORM helpers, or unrelated bundles.


Class index — wire-protocol concern → class

Wire transport (the layer we're rebuilding in _socket.py + _protocol.py)

Concern Class Path Notes
Raw socket lifecycle, SSL, login orchestration com.informix.asf.Connection build/jdbc-src/com/informix/asf/Connection.java (1228 LOC) The wire-level connection. Owns Socket asfSocket, the buffered streams, IfxDataInputStream/OutputStream. This is what our connections.py layer maps to (just the socket+framing parts; SQL state lives a layer up).
Wire write primitives com.informix.asf.IfxDataOutputStream …/asf/IfxDataOutputStream.java (205 LOC) writeShort, writeInt, writeChar, writeDate, writeDateTime, writeDecimal, writeReal, writeDouble, writeSmallInt, writeLongInt, writeLongBigint, writePadded (16-bit alignment).
Wire read primitives com.informix.asf.IfxDataInputStream …/asf/IfxDataInputStream.java (235 LOC) Mirror of the above: readShort, readInt, readChar (length-prefixed string), readDate, readDateTime, readDecimal, readReal, readDouble, readSmallInt, readLongInt, readLongBigint, readPadded.
Protocol tracing (logging hook) com.informix.asf.SqliDbg …/asf/SqliDbg.java (135 LOC) Records C2S / S2C transitions. Worth reading to learn which fields IBM thinks are interesting enough to log.
Debug-instrumented streams com.informix.asf.IfxDebugDataInputStream / OutputStream …/asf/IfxDebug*.java Subclasses of the regular streams that emit trace records. Used when SQLITRACEFILE opt-prop is set.
HTTP-tunneled SQLI com.informix.asf.HttpConnection, HttpBufferedInputStream, HttpBufferedOutputStream …/asf/Http*.java SQLI-over-HTTP for proxy/firewall traversal. Phase 6+ at the earliest. Skip for MVP.

Type encoding/decoding (JavaToIfx ↔ IfxToJava)

Concern Class Path Notes
Java→wire encoders com.informix.lang.JavaToIfxType …/lang/JavaToIfxType.java JavaToIfxInt(int) → 4-byte BE; JavaToIfxSmallInt(short) → 2-byte BE; JavaToIfxLongBigInt(long) → 8-byte BE; JavaToIfxLongInt(long) → 10-byte legacy variable-numeric (skip MVP); JavaToIfxChar(String) length-prefixed; JavaToIfxDate, JavaToIfxDateTime, JavaToIfxDecimal, JavaToIfxReal, JavaToIfxDouble.
Wire→Java decoders com.informix.lang.IfxToJavaType …/lang/IfxToJavaType.java Mirror of the above.
IDS type metadata / type codes com.informix.lang.IfxTypes …/lang/IfxTypes.java Constants for the IDS internal type IDs. The other half of the answer to "what's in column descriptors".
INTERVAL day-fraction / year-month structures com.informix.lang.IntervalDF, IntervalYM, Interval …/lang/Interval*.java Phase 6+.

SQLI protocol (the layer we're rebuilding in connections.py + cursors.py)

Concern Class Path Notes
Protocol contract com.informix.jdbc.IfxProtocol (interface) …/jdbc/IfxProtocol.java (146 LOC) 50-method interface — read this FIRST to understand the protocol's "vocabulary" without drowning in implementation. Methods include executeBegin/Commit/Rollback/Savepoint, executeVersion, executeProtocols, handlePAMAuthentication, executeOpenDatabase, executeCommand, executePrepare, executeExecute, executeFetchBlob, executeReadSmBlob, executeFastPath, handlePrivateServerExchange.
SQLI protocol implementation com.informix.jdbc.IfxSqli …/jdbc/IfxSqli.java (6501 LOC) The concrete IfxProtocol impl. Owns IfxDataInputStream is / IfxDataOutputStream os (inherited from IfxSqliConnect). Search for os.writeShort(...) to find every message-emit site.
Connection state machine + login orchestration com.informix.jdbc.IfxSqliConnect …/jdbc/IfxSqliConnect.java (5029 LOC) Holds the com.informix.asf.Connection, owns the high-level connection state. Exposes IfmxConnection.
Message-type tag enumeration com.informix.jdbc.IfxMessageTypes …/jdbc/IfxMessageTypes.java (163 LOC) All 142+ SQLI message type constants. Goldmine. See "Message type tag table" in PROTOCOL_NOTES.md.
JDBC Driver entry point com.informix.jdbc.IfxDriver …/jdbc/IfxDriver.java (584 LOC) URL parsing, property handling, Driver.connect() impl. Useful for understanding what opt-props exist and which ones affect protocol behavior.
Connection extension interface com.informix.jdbc.IfmxConnection (interface) …/jdbc/IfmxConnection.java Adds Informix-specific methods to java.sql.Connection: UDT info, HDR, scrubConnection() for pool reuse, IFX_USEPUT, prepared-statement cache.

Auth handlers

Concern Class Notes
Plain-password auth inline in Connection.encodeAscBinary() Username + password are written into the binary login PDU directly. No separate auth round-trip. MVP target.
Legacy text-mode auth (-pPASSWORD argv) Connection.EncodeAscString() Triggered when capabilities == 0. Emits literal sqlexec USER -pPASSWORD VERSION SERIAL -dDB -fIEEEM argv string. Skip MVP.
PAM challenge/response IfmxPAM, IfxPAMChallenge, IfxPAMResponse; IfxSqli.handlePAMAuthentication(String) Triggered by server-initiated SQ_CHALLENGE=129 → client replies with SQ_RESPONSE=130. Phase 6+.
Trusted Context flag in encodeAscBinary (option bit ASF_TRUSTCTXT = 0x4000000 in stmtoptions int) Phase 6+.
GSSAPI / Kerberos not directly visible in Connection.java; likely handled via JCE provider plumbing Phase 6+ if ever.
CSM is removed Connection.getOptProperties() throws "CSM Encryption is no longer supported" if SECURITY or CSM is set Confirmed dead. Cross off forever.
SSL / TLS inline in Connection.openSocket() Wraps Socket with SSLSocket. Default protocols: TLSv1.3, TLSv1.2, TLSv1.1, TLSv1 (Java 11+). Phase 6+.

Errors

Concern Class Notes
Error code → message text com.informix.util.IfxErrMsg Maps SQLCODE to localized text. Used to construct exceptions and warnings. The Message CLI tool (com.informix.jdbc.Message) is just a thin wrapper.
Warning code → message text com.informix.util.IfxWarnMsg Same, for warnings.
ASF-level (transport) exceptions com.informix.asf.IfxASFException, IfxASFRemoteException Network / login-rejection errors. Distinct from SQL-level exceptions.
Tracing com.informix.util.Trace, TraceFlag Used throughout.

Stuff to ignore

  • com.informix.jdbc.types.*, com.informix.jdbc.udt.* — JDBC API helpers, not protocol
  • com.informix.jdbcx.* — DataSource/XA/Pool wrappers; sit ABOVE the protocol layer
  • com.informix.jns.* — sqlhosts lookup; not relevant when we just connect to host:port directly
  • com.informix.judr.* — Java UDR support; not protocol
  • com.informix.smartTrigger.* — event-subscription feature; not MVP
  • com.informix.jdbc.IfxBlob, IfxClob, IfxLob*, IfxSmBlob, IfxSmartLobOutputStream — large object support; Phase 6+
  • org.bson.* — bundled MongoDB BSON; for the JSON/BSON column type. Phase 6+ at best
  • com.informix.jdbc.IfxBSONObject, IfxJSON, IfxImpExp — BSON/JSON wrappers and import/export utilities

Method-level pointers (specific Java methods → wire effect)

Format: Class#method() → wire bytes emitted/consumed. Filled in as we read deeper.

Connection / login

  • com.informix.asf.Connection#openSocket() → opens the TCP (or SSL) socket to ipAddr:PortNumber, sets TCP_NODELAY, optional KEEPALIVE.
  • com.informix.asf.Connection#sendConnectionRequest(...) → emits the binary login PDU (encodeAscBinary path) or legacy text login (EncodeAscString path).
  • com.informix.asf.Connection#encodeAscBinary(...) → emits the binary login PDU. See PROTOCOL_NOTES.md §2 Login Sequence for the byte-by-byte breakdown. Markers used: 100, 101, 104, 106, 107, 108, 116, 127.
  • com.informix.asf.Connection#EncodeSLheader(o, pfPDUsize, slType, slAttribute, slOptions) → 6-byte SL header preceding the binary login: [short totalSize][byte slType][byte slAttribute][short slOptions].
  • com.informix.asf.Connection#EncodeAscString(...) → emits the legacy text login: "sqlexec USER -pPASSWORD VERSION SERIAL -dDB -fIEEEM ".
  • com.informix.asf.Connection#recvConnectionResponse() → reads [short length][byte SLType][skipBytes 3][markers 100,101][...] → dispatches to DecodeAscBinary / DecodeAscString.
  • com.informix.asf.Connection#DecodeAscBinary(in) → reads server response: VersionNumber, SerialNumber, ApplidName, Cap_1, Cap_2, Cap_3, then a switch on a marker (102=SQ_ASCINITRESP, 103=redirect, 127=SQ_ASCEOT clean).
  • com.informix.asf.Connection#disconnectOrderly() → sends bare [short SQ_EXIT=56], expects server to echo back [short 56] or [short 12=SQ_EOT]. May receive interleaved [short 99=SQ_XACTSTAT] mid-stream.

Type encoding

  • com.informix.lang.JavaToIfxType#JavaToIfxInt(int) → 4-byte big-endian.
  • com.informix.lang.JavaToIfxType#JavaToIfxSmallInt(short) → 2-byte big-endian.
  • com.informix.lang.JavaToIfxType#JavaToIfxLongBigInt(long) → 8-byte big-endian (BIGINT type).
  • com.informix.lang.JavaToIfxType#JavaToIfxChar(String) → returns [short length+1][bytes][0x00 nul terminator]. The +1 accounts for the trailing nul.
  • com.informix.asf.IfxDataOutputStream#writePadded(byte[]) → write bytes, then write a 0x00 byte if length is odd. The 16-bit-alignment requirement.

Disconnect

  • com.informix.asf.Connection#disconnectOrderly() (above)
  • Bare [short 56] is the only message the client emits; bare [short 56] or [short 12] is the response. No header.

Useful greps

# Find every wire-emit site in IfxSqli.java (writeShort calls reveal message tags being sent)
grep -nE 'os\.writeShort\(' build/jdbc-src/com/informix/jdbc/IfxSqli.java

# Find every wire-read site
grep -nE '\.readShort\(\)' build/jdbc-src/com/informix/jdbc/IfxSqli.java

# Find login state-machine logic
grep -nE 'executeOpenDatabase|executeVersion|executeProtocols|handlePAM|handlePrivate' build/jdbc-src/com/informix/jdbc/IfxSqli.java

# Find type-codec dispatch
grep -nE 'switch.*[Cc]olType|case.*IfxTypes\.' build/jdbc-src/com/informix/jdbc/IfxSqli.java

# Authentication strings
grep -rln 'OBFUSCATE\|PWDOBFUSCATION\|GSS\|KERBEROS' build/jdbc-src/

# SQLSTATE / error mapping
grep -rln 'SQLSTATE' build/jdbc-src/