Skip to content

Remove smbj: replace SMB file copy with a transfer through the WinRM command shell #117

Description

@bertysentry

Goal

Remove com.hierynomus:smbj — the last runtime dependency of winrm-java — and replace the SMB-based temporary-share file copy with a file transfer performed through the WinRM command shell itself, the way dependency-free clients like pywinrm (Copy-Item helpers), winrs-based tooling, and Ansible's win_copy do it.

This is the final step of the zero-dependency goal of the winrm-light effort (#103#108) and the actual fix for #116:

com.hierynomus:smbj:0.14.0          0.58 MB
├─ org.bouncycastle:bcprov-jdk18on  8.18 MB   (90% of the ~9 MB standalone CLI JAR, #112)
├─ org.slf4j:slf4j-api              0.06 MB   (#116)
├─ net.engio:mbassador              0.09 MB
└─ com.hierynomus:asn-one           0.06 MB

smbj cannot run on stock JDK crypto (it needs MD4 for NTLM, AES-CMAC for SMB 3.x signing, AES-CCM for SMB 3.x encryption — none of which are in SunJCE), which is why it drags in BouncyCastle. Removing smbj removes all of the above in one move and takes the standalone JAR from ~9 MB to a few hundred KB.

Proposed design

Transfer the file over the already-authenticated, already-encrypted WinRM channel — no new port (445), no separate SMB authentication, works through firewalls that only allow 5985/5986:

  1. Base64-encode the local file and split it into chunks that fit comfortably within the WinRM MaxEnvelopeSize (pywinrm/Ansible use ~1 KB–8 KB per command leg; we can size chunks dynamically from the negotiated envelope size).
  2. Append each chunk on the remote side via the command shell, e.g. echo <chunk> >> C:\Windows\Temp\<name>.b64.tmp, or preferably a single PowerShell invocation that reads chunks from stdin to reduce round-trips.
  3. Decode once at the end: certutil -decode or PowerShell [IO.File]::WriteAllBytes(..., [Convert]::FromBase64String((Get-Content ...))), then delete the temp .b64 file.
  4. Verify integrity by comparing a hash (certutil -hashfile / Get-FileHash SHA-256) against the locally computed digest; fail with a WindowsRemoteException on mismatch.
  5. Clean up the remote temp artifacts on failure paths too.

Performance note: base64-over-SOAP is slower than SMB for large payloads. That is acceptable — the existing SmbTempShare/WindowsTempShare use case is copying small script files for execution, not bulk data. Document the expected use (small files) and consider a size guard with a clear error message.

Scope

  • Reimplement the SmbTempShare functionality (temporary remote directory + file copy + cleanup) on top of WindowsRemoteExecutor.executeCommand(...); keep the public API (WindowsTempShare contract) as stable as possible.
  • Delete the smbj dependency from pom.xml.
  • The standalone CLI JAR (Add a WinRM CLI and standalone executable JAR #112) shrinks accordingly with no shade-plugin exclusions needed.

Acceptance criteria

  • mvn dependency:tree shows zero runtime/compile dependencies (test scope only).
  • No org.bouncycastle, org.slf4j, net.engio, or com.hierynomus classes in the standalone JAR; JAR size back to a few hundred KB.
  • File copy works live against a real Windows host over NTLM/HTTP (encrypted) and HTTPS, including: file with multibyte UTF-8 content, binary file, empty file, and a file large enough to require multiple chunks.
  • Hash verification failure and mid-transfer errors surface as exceptions (no logging, per Remove SLF4J: the library must not depend on any logging framework #116) and leave no orphaned temp files on the remote host.
  • Unit tests cover chunking, encoding, and failure paths; live coverage added to the existing live-test rig.

Closes the dependency-removal half of #116 (SLF4J) as a side effect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions