Stage 1R was performed on 2026-08-09 against one authorized MegaRAC SP lab BMC corresponding to the supplied JViewer artifacts. It answers the bounded questions that static bytecode could not answer before Stage 2. Results in this document are firmware/session-specific observations, not universal MegaRAC guarantees.
The initial Stage 1R probes used only the normal web login, fresh JNLP acquisition, the legacy KVM authentication/start/pause/resume/stop messages, and one virtual-media authentication exchange. A later Stage 4 follow-up sent one exact JViewer resume-time relative mouse report whose buttons, X/Y deltas, and wheel were all zero. A second Stage 4 control run relayed an otherwise unaltered original JViewer connection solely to count its plaintext IVTP packet types. No key, click, nonzero movement, configuration change, power action, media mount, SCSI service loop, or unknown opcode was sent.
Raw application streams contain credentials, session material, and potentially
screen data. They remain below Git-ignored docs/captures/private/ with
directory mode 0700 and file mode 0600. Only categorical or structural
results are recorded here. Packet capture through BPF was unavailable to the
unprivileged research account, so the probes captured the plaintext bytes at
the application socket boundary.
The stdlib-only helpers created for this validation are:
research/scripts/megarac_auth.py: normal login, cookie jar, validation, bounded JNLP fetch, and redacted summary;research/scripts/dump_jnlp.py: secret-safe structural JNLP inspection;research/scripts/session_lifecycle_probe.py: independent issuance and silent-idle observations;research/scripts/kvm_probe.py: bounded IVTP handshake, raw capture, fragment/frame telemetry, refresh, and idle scenarios;research/scripts/vmedia_probe.py: one CD-class IUSB authentication frame and one bounded acknowledgement, with no media source or SCSI loop.
Offline regression tests cover truncated GoAhead responses, negative HAPI status values, XML hardening, secret redaction, exact type-18 construction, fragmented TCP reads, IVTP limits/state transitions, frame telemetry, capture permissions, the IUSB two-pass checksum, and acknowledgement bounds.
Symbolic examples:
python3 research/scripts/megarac_auth.py \
--host HOST --user USER --scheme http
python3 research/scripts/kvm_probe.py \
--host HOST --user USER --scheme http --mode baseline
python3 research/scripts/session_lifecycle_probe.py idle-expiry \
--host HOST --user USER --scheme http --delay-seconds 300
python3 research/scripts/vmedia_probe.py \
--host HOST --user USER --scheme http --mode validLUNARVIEW_TEST_PASSWORD was used only for the authorized automated run. The
password, web-session value, and KVM token are never printed by these tools.
The live web assets identify and the BMC confirms this normal flow:
- POST
/rpc/WEBSES/create.aspwithWEBVAR_USERNAMEfollowed byWEBVAR_PASSWORD. - Parse JavaScript data, not JSON, for exactly one
HAPI_STATUSand one quotedSESSION_COOKIE. - Insert
SessionCookieinto a real cookie jar. The server itself sets only an unrelated test cookie; the browser JavaScript performs this insertion. - GET
/rpc/WEBSES/validate.aspand require status zero. - GET
/Java/jviewer.jnlpwith the UI's two query parameters and parse exactly 15 direct application arguments.
The RPC bodies have no reliable HTTP length delimiter and end at the semantic
marker //Dynamic data end. The captured JNLP declared a longer
Content-Length than its complete XML body; bounded reading through </jnlp>
was therefore required. HTTP/1.1 plus Connection: close worked on this BMC;
the HTTP/1.0 compatibility switch was not needed. The lab endpoint used
plaintext HTTP, so the research helper reports that credential-transport
warning rather than hiding it.
One nonexistent username attempt and one wrong-password attempt produced
byte-identical bodies with HAPI_STATUS=-6 and no usable session value. This
firmware does not expose enough information to distinguish those two causes;
the correct diagnostic is “invalid username or password.” A valid login
immediately afterwards succeeded, so the bounded negative tests did not lock
the account.
The fresh JNLP result confirmed all 15 positions documented in
jviewer-arguments.md. Its final argument exactly matched the login
web-session value, while argument 3 was a separate KVM token. The JNLP
codebase scheme differed from the acquisition scheme, so scheme equality is
not a valid parser requirement.
| Experiment | Runtime observation | Bounded conclusion |
|---|---|---|
| Three independent login/JNLP/logout flows | All three 35-byte ASCII web-session values were distinct; all three 16-byte ASCII KVM tokens were distinct; nonsensitive endpoint/count/flag arguments were stable | Both secret values are newly issued per login/JNLP flow on this firmware |
| Two deliberate JNLP GETs in one web session | KVM tokens were distinct; the web-session value and all public arguments were unchanged | A new JNLP refreshes the KVM token without replacing the web cookie |
| Silent web session for 300 seconds | A single validation after the silent interval returned status zero; logout then succeeded | Web-session validity is at least 300 seconds; exact TTL is not determined |
| Validate immediately after explicit logout | Validation returned nonzero status 2 | Logout invalidates the web session for the validation endpoint |
| KVM immediately after web logout | KVM type 19 accepted the already issued token | Web logout does not immediately revoke that KVM token |
| KVM after web logout plus 300 seconds of silence | KVM type 19 still accepted | KVM-token validity after logout is at least 300 seconds; exact TTL is not determined |
A finite successful idle interval can establish only a lower bound. No claim of “no expiry” is made, and the validation endpoint was not polled during the silent interval because polling could refresh server-side activity.
The baseline capture observed:
server 23
client 21 (raw web-session body)
client 18 (132 transmitted bytes; header pktSize 140)
client 6
server 19 (one nonzero byte)
server 20, 10, 20, 4099
client 8 during bounded cleanup
This proves that the exact legacy type-18 inconsistency is accepted by this BMC: the 8-byte header declares 140 body bytes, while the client transmits only 124 body bytes. The next 8-byte type-6 header was not consumed as missing type-18 payload; all later control packets remained correctly framed.
A split experiment held type 6 for two seconds after the last type-18 byte. No type-19 response arrived during the delay. A nonzero type 19 arrived about two milliseconds after type 6. The observable rule is therefore:
- the BMC preserves the 132-byte type-18 boundary despite
pktSize=140; - this firmware does not acknowledge validation independently during the observed delay;
- type 6 triggers or gates the validation response.
The capture cannot reveal the internal implementation or why the historical length field is 140. LunarView must preserve the proven 132-byte wire form.
Each mutation below was a single controlled attempt with a freshly issued session; there was no guessing or retry loop.
| Type-21/type-18 material | Type-19 result |
|---|---|
| Matching fresh web-session value and KVM token | accepted |
| Web-session value from fresh session A plus KVM token from fresh session B | accepted |
| One-character mutation of an otherwise fresh KVM token | rejected |
| One-character mutation of an otherwise fresh web-session value | accepted |
| Matching credentials with an all-zero textual embedded local-IP field | accepted |
For this firmware, the primary KVM token is the value whose exact content is validated. The captured KVM path did not require the type-21 body to match a live web-session value, did not pair it with a particular KVM token, and did not require the embedded textual IP to equal the TCP source address. This does not prove that type 21 may be omitted or malformed; only an exact-value change was tested while preserving its framing.
Network-source binding could not be tested because the workstation had only one usable on-link source address. No interface alias or routing change was made solely to manufacture another source.
The accepted session returned:
- type 10 with value 1, selecting the documented relative mouse mode;
- type 20 with the same one-byte LED state twice;
- type 4099 with eight configuration bytes. Compression mode was zero (documented YUV 4:2:0), and the VGA-DAC/host-video-output field was zero.
The initial captures sent no HID. The later refresh-hid follow-up waited for
type 10 value 1, then reproduced the otherwise-missing JViewer resume behavior:
type 4, type 6, and one 45-byte plaintext type-1 relative mouse report with
sequence zero and all four report bytes zero. The server kept the session open
and continued with normal type 20/4099 control state, but there is no explicit
HID acknowledgement, so this is not proof of general generated-input support.
No type-25 video fragment arrived in either of two captures:
- 180 seconds after a normal accepted baseline handshake;
- 120 seconds after an accepted handshake followed by the same type-4 then type-6 refresh sequence used by the JViewer UI.
Nor did a fragment arrive during the 20-second refresh-hid follow-up after
the exact type-4, type-6, zero-relative-HID resume sequence. Thus the earlier
video silence is not explained by omission of that JViewer-generated report.
Finally, a fresh original JViewer process was run for 60 seconds through a
bounded localhost TCP relay. The normal standalone launcher first had to be
given a private test-only JNI shim for its keyboard-layout query: Java Web Start
would have loaded the historical native bundle, while the local launcher only
placed that bundle on java.library.path; loading the original library itself
is no longer possible on this host because it names removed X11/libstdc++
paths. The shim returned only the US keyboard-layout identifier and did not
intercept or alter KVM traffic. The legacy process remained healthy and the
BMC accepted type 19. Its complete client stream was exactly types 21, 18, and
6; the server stream was types 23, 19, 10, 20 (twice), and 4099. It contained
zero type-25 packets and parsed without trailing or malformed bytes. Raw relay
streams remain private and ignored.
This control establishes that the supplied original viewer also received no video from the current lab state. The missing frame is therefore not evidence of a LunarView/Python handshake divergence.
The read-only web power-status endpoint reported the host as powered on, and
the eighth type-4099 field was zero. JViewer names that field vga_dac and
maps it to the Host Video Output menu item, but does not use it to gate
streaming or decoding. Its zero value therefore does not establish the cause
of video silence. Changing that setting or sending host input would have
exceeded the capture-only boundary, so neither was done. Consequently this
environment did not yield runtime evidence for fragment markers, start code,
frame-number lifecycle, compressed-size agreement, resolution, RC4 flags,
keyframe cadence, or damaged-frame recovery. The transport and authentication
are proven; the remaining gap is the unexplained absence of type-25 packets,
not an observed IVTP framing failure.
After the initial state packets, the baseline KVM socket remained connected without any client transmission for the rest of the 180-second observation. The server sent no periodic packet after its final configuration response near the start of the session. Type 8 and web logout then completed normally.
This gives a KVM idle-tolerance lower bound of 180 seconds and confirms no server-originated periodic heartbeat in that window. It does not establish an infinite timeout or the configured disconnect threshold. A paused-video idle comparison could not reach its required first-frame boundary because no video frame arrived.
The valid CD-class probe reproduced the Java client's fresh zeroed
131,134-byte buffer and both aliased IUSBHeader.write passes. For device
index zero, the transmitted 160-byte auth frame has an additive byte sum of
0xDA, not zero. The BMC returned a 55-byte-payload 0xF1 acknowledgement
with connection status 1.
The server acknowledgement itself used zero for major, minor, and the packet header-length field. The Java reader stores but does not validate those fields; the initial strict runtime parser exposed this difference and was narrowed to the two observed/constructed header-length values without weakening the signature or payload bounds.
A second probe changed only the low bit of final wire offset 11 after both
legacy checksum passes. Its transmitted additive sum changed from 0xDA to
0xDB, yet the BMC returned the same 0xF1, status-1 acceptance. Therefore
this firmware does not enforce the IUSB header checksum on the initial
virtual-media authentication frame.
Both sockets were closed immediately after the single acknowledgement. No
local source was opened, no media-state notification was sent on KVM, and no
SCSI request was serviced. Checksum handling on later SCSI traffic, opaque
native envelope fields, sequence policy, and the hard-disk 0xF4 extension
remain untested; resolving them requires an explicitly approved nonsensitive
test medium.
The authenticated live navigation bundle contains Console Redirection and Virtual Media pages but no serial, terminal, COM-redirection, or SOL entry. This strengthens the artifact-level negative result for this web/JViewer bundle. It still does not test the BMC's separate IPMI SOL capability, which would require a different client/protocol and authorization scope.
Stage 1R resolves or bounds the practical static unknowns as follows:
- exact legacy web login and malformed-length JNLP acquisition: confirmed;
- type-18 wire acceptance and next-packet framing: confirmed;
- KVM token validation versus cookie/IP fields: experimentally separated;
- token/cookie issuance and same-session JNLP refresh: confirmed;
- web-session and post-logout KVM-token lifetime: at least 300 seconds;
- KVM idle tolerance: at least 180 seconds, with no periodic server packet;
- initial virtual-media checksum enforcement: absent on this firmware;
- live relative-mouse mode and video configuration response: confirmed; one zero-state resume report caused no disconnect but has no positive input ACK;
- original JViewer control: accepted for 60 seconds and likewise received no type-25 fragment, isolating the video gap to the current lab/BMC state;
- video-fragment/header/RC4 runtime values: still not observable without a producing video source;
- later virtual-media SCSI semantics: intentionally not exercised without a user-approved benign medium;
- true network-source binding, exact expiry thresholds, IPMI SOL, and cross-firmware behavior: not determinable from this single lab path.
These bounded residuals should remain explicit during Stage 2 comparison; a third-party implementation must not be used to rewrite observed facts from this BMC or the supplied JViewer bytecode.