Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,44 @@ All notable changes to this project are documented in this file.

## [Unreleased] — 2.0.0

### ⚠️ Breaking — SMB file copy replaced by a transfer through the WinRM channel

Files passed to `WinRMCommandExecutor.execute(...)` in `localFileToCopyList` are no longer copied
over SMB: they are transferred **through the WinRM command shell** (chunked base64, decoded with
`certutil -decode`, verified with a `certutil -hashfile` digest against the locally computed one).
Consequences:

- **Zero runtime dependencies**: `smbj` is gone, and with it BouncyCastle (`bcprov-jdk18on`,
8.2 MB and a recurring source of CVE churn), `slf4j-api`, `mbassador`, and `asn-one`. The
standalone CLI JAR shrinks from ~9 MB to a few hundred kB, and the library no longer references
any logging API — problems are reported through exceptions only.
- **No SMB requirement**: TCP port 445 does not need to be reachable, no administrative/temporary
share is created on the remote host (`net share` is no longer issued), and the copy now works
from any client OS (the previous implementation wrote through a Windows UNC path, which only
worked from a Windows client with ambient access to the share).
- A file already present in the remote temporary directory with an identical digest is not
transferred again, preserving the caching behavior of repeated script executions.
- The remote copy is **content-addressed**: a fragment of the content digest is inserted before
the file extension (e.g. `script.1a2b3c4d5e6f.vbs`), so same-named files with different content
from concurrent clients can never overwrite each other. Scripts that inspect their own file
name (e.g. `WScript.ScriptName`) will see the digest fragment. Overlong names are truncated so
that both the NTFS path-component limit and the traditional Windows `MAX_PATH` (260) full-path
limit hold, staging suffixes included (the digest keeps truncated names unique).
- The transfer is decoded into an operation-unique staging file, verified there, and only then
published as the content-addressed destination. A destination that already carries the
expected digest is never rewritten (so concurrent transfers of the same content cannot
invalidate a copy already verified by another operation), while a mismatched pre-existing
copy (e.g. corrupted in place) is repaired by replacement. In every case, the destination's
digest is verified last: the operation fails rather than execute unproven bytes.
- The transfer is designed for the small script files this API is meant for; base64 over SOAP is
not suited to bulk data.
- Transfer steps are batched to minimize WinRM operations (the digest probe rides the same
command leg as the decode and publish steps), and a command rejected by the server-side
concurrent-operation quota — very low on old hosts (15 per user on Windows 2008 R2) — is
retried with a delay when the rejection happened before the command could run.
- `SmbTempShare` (class) and `WindowsRemoteProcessUtils.copyLocalFilesToShare(...)` were removed.
`WindowsTempShare` is unchanged.

### ⚠️ Breaking — the CXF backend was removed

Version 2.0.0 removes the legacy Apache CXF backend. The dependency-free client introduced in the
Expand All @@ -20,14 +58,18 @@ unaffected. Consequences:
(**insecure — for testing only**).
- Setting `-Dorg.metricshub.winrm.backend=cxf` now fails with a clear error instead of selecting
the removed backend: remove the property (or stay on winrm-java 1.x).
- The jar shrinks dramatically: the Apache CXF / JAX-WS / JAXB stack is gone and the only runtime
dependency left is `smbj` (used for copying files to remote shares).
- The jar shrinks dramatically: the Apache CXF / JAX-WS / JAXB stack is gone, and with the SMB
file copy replaced by a WinRM-native transfer (see above), the library has **zero runtime
dependencies**.

### Removed

- The Apache CXF-based backend (`WinRMService` and the `service.client` internals), the CXF /
JAX-WS / JAXB / `jaxws-rt` dependencies, and the WSDL/XSD resources and code generation.
- `KerberosCredentialsException` (was thrown only by CXF internals).
- The `smbj` dependency (and its transitive BouncyCastle, SLF4J, `mbassador`, and `asn-one`),
`SmbTempShare`, and `WindowsRemoteProcessUtils.copyLocalFilesToShare(...)` — replaced by the
file transfer through the WinRM command shell.

### Added

Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ The Windows Remote Management (WinRM) Java Client is a library that enables to:

## The WinRM client

The client is dependency-free (no Apache CXF / JAX-WS / JAXB — the only runtime dependency is
`smbj`, used for copying files to remote shares) and immune by construction to JAXP
The client has **zero runtime dependencies** (no Apache CXF / JAX-WS / JAXB, no BouncyCastle, no
SLF4J — problems are reported through exceptions only) and is immune by construction to JAXP
`ServiceLoader` conflicts (it uses the JDK-default XML factories). It supports **NTLM over HTTP
(with message encryption) and HTTPS** and **Kerberos (SPNEGO) over HTTPS**. Over HTTPS it
(with message encryption) and HTTPS** and **Kerberos (SPNEGO) over HTTPS**.

Files listed in `localFileToCopyList` are copied to the remote host **through the WinRM channel
itself** (chunked base64 through the command shell, decoded with `certutil` and verified with a
digest): no SMB, no TCP port 445, no administrative share — and it works from any client OS. A
file already present on the remote host with an identical digest is not transferred again. This
transport is designed for small script files, not bulk data. Over HTTPS it
validates the certificate and verifies the hostname by default (see the upgrade warning above);
`-Dorg.metricshub.winrm.tls.insecure=true` trusts all certificates (insecure, testing only).
Kerberos uses the ambient Kerberos configuration (`krb5.conf` / `-Djava.security.krb5.*`) unless
Expand Down
13 changes: 0 additions & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,6 @@
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>smbj</artifactId>
<version>0.14.0</version>
</dependency>
<!-- Override the vulnerable version pulled transitively by smbj (GHSA-574f-3g2m-x479, GHSA-c3fc-8qff-9hwx);
declared as a direct runtime dependency so downstream consumers get the fixed version too -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.85</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
Expand Down
Loading
Loading