Skip to content

Commit

Permalink
Split off from 0.10.0 without the reworked authentication fixes (#762)
Browse files Browse the repository at this point in the history
* Ignore VSCode

* Add NtStatus.STATUS_UNSUCCESSFUL

* Add NtStatus.STATUS_INSUFF_SERVER_RESOURCES (#611)

* Add NtStatus.STATUS_IO_REPARSE_TAG_NOT_HANDLED (#514)

* Update gradle build

* Update release plugin

* Release version: 0.11.0

* Fix signing task dependency

* Release version: 0.11.1

* Use BCSecurityProvider by default for SMB3 compatibility (Fixes #638)

* Ensure DFS Path Referral times out after transactTimeout (Fixes #578)

* Only add DFSPathResolver if both client and server support DFS (#640)

* Only add DFSPathResolver if both client and server support DFS

* Fix indentation problems

* Fix incorrectly reformatted javadoc

* Format using java formatter

* One more indentation fix

* Upgrade Bouncy Castle to 1.68 to fix vulnerability report (#641)

* address issue #604 - stop closing the dfs share connection immediately. (#609)

* stop closing the dfs share connection immediately.

* Add explanatory comment

Co-authored-by: Jeroen van Erp <jeroen@hierynomus.com>

* Add support for unregistering server from serverlist (Fixes #644) (#647)

* Add support for unregistering server from serverlist (Fixes #644)

* Fix indentation

* Reducing logging for smb3 (#650)

For each smb3 packet there's an info log message which produces a tremendous amount of output.
I would suggest to reduce log level to debug (or trace; similarly as in one of the other packet reciever classes).

* Consolidate SMBv1 error messages

* Upgrade BouncyCastle to 1.69

* Release version: 0.11.2

* Ensure artifact is signed

* Release version: 0.11.3

* Fix #665: Allow JCE KDF to work (#666)

* Fix #665: Allow JCE KDF to work

* Add header

* Add KDF unit test

* Use correct maxPayloadSize for encrypted packets (Fixes #668) (#683)

* Read fileId as long (#693)

* Read fileId of FileIdBothDirectoryInformation into a long
* Read fileId of FileIdFullDirectoryInformation into a long

* File the issue that nested folder creation throw NAME EXIST error. (#685)

* File the issue that nested folder creation throw NAME EXIST error.

* formatting

* Updated build status badges (#684)

- Added GitHub badge for Build SMBJ
- Corrected Codacy badge link
- Removed bintray badge link
- Removed Travis CI badge and configuration
- Removed Java profiler link
- Removed CircleCI configuration
- Removed unused github-ci configuration

* Use AceSize field when reading ACEs (#696)

Fixes issue seen in the wild where unnecessary padding at the end of an ACE
confused Smbj (but not Windows).

* Ensure that enough bytes are cached from InputStream to get a correct bytesLeft count for SMB2Write (fixes #669)

* GzipOutputStream integration test

* Ensure that enough bytes are cached from InputStream to get a correct bytesLeft count for SMB2Write

Co-authored-by: Stanislav Kardashov <skardashov@spins.com>
Co-authored-by: Jeroen van Erp <jeroen@hierynomus.com>

* Add GH workflow for publishing

* Update dependencies and build file

* Rename test class to *Spec

* Release version: 0.11.5

* Use the hostname part of the TargetHint for DFS step 9 (fixes \#419) (#722)

* Slightly reduce the locking in Connection.send and DirectTcpTransport (fixes \#732)

* Fixed indentation

* Converting bytes written to long (Fixes #740)

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Upgrading gradle to 8.0.2

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Add Implementation manifest attributes (Fixes #743)

* Revert accidental comment of integration docker tasks

* Do not send SMB2EncryptionCapabilities NegotiationContext is !isEncry… (#752)

* Do not send SMB2EncryptionCapabilities NegotiationContext is !isEncryptionSupported (Fixes #747)

* Add test for SMB2EncryptionCapabilities

* Add preliminary changelog for new release

* Ensure we call flip() on Buffer to avoid Java8 problems (Fixes #705)

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Ensure path is set for rmdir to prevent accidents (Fixes #756)

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Add support for reading / writing NIO ByteBuffers (#759)

* Add support for reading / writing NIO ByteBuffers

Currently one can transfer data using streams or array, but it would be
great to have the opportunity to use NIO buffers.

This adds two new method to the File class that accept a NIO ByteBuffer.

* Implemented ByteBuffer write using ByteChunkProvider

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

---------

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>
Co-authored-by: Christoph Läubrich <christoph@laeubi-soft.de>
Co-authored-by: Jeroen van Erp <jeroen@hierynomus.com>

* Fix some sonatype warnings

* resolve conflict with master

* Ignore non-semver tags for release workflow

* Small warning cleanup

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Setup ConnectionContext and AuthenticationContext for NTLM improvements

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Refactor TargetInfo/AvPairs

* Added null check and rename field

* Refactor NtlmFunctions

* Change hierarchy of Ntlm messages

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Next step of NTLM refactor

* NtlmNegotiate sends Domain/Workstation/Version fields

* Filter negotiateflags and use clientTargetInfo

* Rework keys in NtlmAuthenticator

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Change to structure of NtlmAuthenticate

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

* Added last changes

Required to put withIntegrity = false still, due to missing mechListMIC

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>

---------

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>
Co-authored-by: Nicholas DiPiazza <nicholas.dipiazza@lucidworks.com>
Co-authored-by: ndimitry <18209884+ndimitry@users.noreply.github.com>
Co-authored-by: Patrick Boyd <pboyd04@gmail.com>
Co-authored-by: Hannes <65758037+hannosgit@users.noreply.github.com>
Co-authored-by: pyzhou <pyzhou@talend.com>
Co-authored-by: exceptionfactory <exceptionfactory@apache.org>
Co-authored-by: Chris Pacejo <chris@pacejo.net>
Co-authored-by: Stanislav Kardashov <stanislav.kardashov@gmail.com>
Co-authored-by: Stanislav Kardashov <skardashov@spins.com>
Co-authored-by: Christoph Läubrich <mail@laeubi-soft.de>
Co-authored-by: Christoph Läubrich <christoph@laeubi-soft.de>
  • Loading branch information
12 people committed Jul 3, 2023
1 parent da24803 commit c81367c
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 84 deletions.
12 changes: 12 additions & 0 deletions WORKING_AUTH_TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Missing commit: 10001efcf7b5beee6994fb0e4a3680a6503f6eab
Extract TargetInfo to separate class and correct offsets for NtlmNegotiate (#630)

* Extract TargetInfo to separate class and correct offsets for NtlmNegotiate

* Add Target SPN AvId if NTLMSSP_REQUEST_TARGET set

* Use clientTargetInfo to calculate NTLM clientChallenge
------
Missing commit: 3e454de9a29db2ef0896af60573378ea7ba4fa4b
Fix ClassCastException (fixes \#712)
------
32 changes: 27 additions & 5 deletions src/main/java/com/hierynomus/ntlm/NtlmConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package com.hierynomus.ntlm;

import java.security.SecureRandom;
import java.util.Random;

import com.hierynomus.ntlm.messages.WindowsVersion;
import com.hierynomus.ntlm.messages.WindowsVersion.NtlmRevisionCurrent;
import com.hierynomus.ntlm.messages.WindowsVersion.ProductMajorVersion;
Expand All @@ -25,13 +28,14 @@ public class NtlmConfig {
private String workstationName;
private boolean integrity;
private boolean omitVersion;
private byte[] machineID;

public static NtlmConfig defaultConfig() {
return builder().build();
return builder(new SecureRandom()).build();
}

public static Builder builder() {
return new Builder();
public static Builder builder(Random r) {
return new Builder(r);
}

private NtlmConfig() {
Expand All @@ -42,6 +46,7 @@ private NtlmConfig(NtlmConfig other) {
this.workstationName = other.workstationName;
this.integrity = other.integrity;
this.omitVersion = other.omitVersion;
this.machineID = other.machineID;
}

public WindowsVersion getWindowsVersion() {
Expand All @@ -60,14 +65,20 @@ public boolean isOmitVersion() {
return omitVersion;
}

public byte[] getMachineID() {
return machineID;
}

public static class Builder {
private NtlmConfig config;

public Builder() {
public Builder(Random r) {
config = new NtlmConfig();
config.windowsVersion = new WindowsVersion(ProductMajorVersion.WINDOWS_MAJOR_VERSION_6, ProductMinorVersion.WINDOWS_MINOR_VERSION_1, 7600, NtlmRevisionCurrent.NTLMSSP_REVISION_W2K3);
config.integrity = false; // TODO temporarily disabled until we can figure out why it fails (probably mechListMIC in NegTokenTarg)
config.integrity = false;
config.omitVersion = false;
config.machineID = new byte[32];
r.nextBytes(config.machineID);
}

public Builder withWindowsVersion(WindowsVersion windowsVersion) {
Expand All @@ -90,6 +101,17 @@ public Builder withOmitVersion(boolean omitVersion) {
return this;
}

public Builder withMachineID(byte[] machineID) {
if (machineID == null) {
throw new IllegalArgumentException("MachineID must not be null");
}
if (machineID.length != 32) {
throw new IllegalArgumentException("MachineID must be 32 bytes");
}
config.machineID = machineID;
return this;
}

public NtlmConfig build() {
return new NtlmConfig(config);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public class AvPairChannelBindings extends AvPair<byte[]> {
super(AvId.MsvAvChannelBindings);
}

public AvPairChannelBindings(byte[] value) {
super(AvId.MsvAvChannelBindings, value);
}

@Override
public void write(Buffer<?> buffer) {
buffer.putUInt16((int) this.avId.getValue()); // AvId (2 bytes)
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/hierynomus/ntlm/av/AvPairSingleHost.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public class AvPairSingleHost extends AvPair<byte[]> {
super(AvId.MsvAvSingleHost);
}

public AvPairSingleHost(byte[] value, byte[] machineID) {
super(AvId.MsvAvSingleHost, value);
this.machineID = machineID;
}

public AvPairSingleHost read(Buffer<?> buffer) throws BufferException {
buffer.readUInt16(); // AvLen (2 bytes)
buffer.readUInt32(); // Size (4 bytes)
Expand Down
84 changes: 37 additions & 47 deletions src/main/java/com/hierynomus/ntlm/messages/NtlmAuthenticate.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.hierynomus.protocol.commons.EnumWithValue;
import com.hierynomus.protocol.commons.buffer.Buffer;
import com.hierynomus.protocol.commons.buffer.Endian;
import com.hierynomus.protocol.commons.buffer.Buffer.PlainBuffer;

import static com.hierynomus.ntlm.messages.Utils.*;

Expand All @@ -45,7 +46,7 @@ public NtlmAuthenticate(
byte[] lmResponse, byte[] ntResponse,
String userName, String domainName, String workstation,
byte[] encryptedRandomSessionKey, Set<NtlmNegotiateFlag> negotiateFlags,
WindowsVersion version, boolean isIntegrityEnabled, boolean isOmitVersion) {
WindowsVersion version) {
super(negotiateFlags, version);
this.lmResponse = ensureNotNull(lmResponse);
this.ntResponse = ensureNotNull(ntResponse);
Expand All @@ -54,70 +55,58 @@ public NtlmAuthenticate(
this.workstation = ensureNotNull(workstation);
this.encryptedRandomSessionKey = ensureNotNull(encryptedRandomSessionKey);
this.negotiateFlags = negotiateFlags;
this.integrityEnabled = isIntegrityEnabled;
this.omitVersion = isOmitVersion;
}

@Override
public void write(Buffer.PlainBuffer buffer) {
private int getBaseMessageSize() {
int baseMessageSize = 64;
if (integrityEnabled) {
baseMessageSize += 16;
}

if (!omitVersion) {
if (negotiateFlags.contains(NtlmNegotiateFlag.NTLMSSP_NEGOTIATE_VERSION) || mic != null) {
baseMessageSize += 8;
}

writeNtlmAuthenticate(buffer, baseMessageSize);

// MIC (16 bytes)
if (mic != null) {
buffer.putRawBytes(mic);
} else if (integrityEnabled) {
buffer.putUInt64(0L);
buffer.putUInt64(0L);
} else {
// Skipping MIC, not enabled.
baseMessageSize += 16;
}

// Payload
buffer.putRawBytes(lmResponse);
buffer.putRawBytes(ntResponse);
buffer.putRawBytes(domainName);
buffer.putRawBytes(userName);
buffer.putRawBytes(workstation);
buffer.putRawBytes(encryptedRandomSessionKey);
return baseMessageSize;
}

public void setMic(byte[] mic) {
this.mic = mic;
}
@Override
public void write(PlainBuffer buffer) {

public void writeNtlmAuthenticate(Buffer.PlainBuffer buffer, int baseMessageSize) {
buffer.putString("NTLMSSP\0", Charsets.UTF_8); // Signature (8 bytes)
buffer.putUInt32(0x03); // MessageType (4 bytes)

int offset = baseMessageSize; // for the offset
int offset = getBaseMessageSize(); // for the offset
offset = writeOffsettedByteArrayFields(buffer, lmResponse, offset); // LmChallengeResponseFields (8 bytes)
offset = writeOffsettedByteArrayFields(buffer, ntResponse, offset); // NtChallengeResponseFields (8 bytes)
offset = writeOffsettedByteArrayFields(buffer, domainName, offset); // DomainNameFields (8 bytes)
offset = writeOffsettedByteArrayFields(buffer, userName, offset); // UserNameFields (8 bytes)
offset = writeOffsettedByteArrayFields(buffer, workstation, offset); // WorkstationFields (8 bytes)
if (negotiateFlags.contains(NtlmNegotiateFlag.NTLMSSP_NEGOTIATE_KEY_EXCH)) { // TODO probably unnecessary check
offset = writeOffsettedByteArrayFields(buffer, encryptedRandomSessionKey, offset);
} else {
offset = writeOffsettedByteArrayFields(buffer, EMPTY, offset);
}
offset = writeOffsettedByteArrayFields(buffer, encryptedRandomSessionKey, offset); // EncryptedRandomSessionKeyFields (8 bytes)

buffer.putUInt32(EnumWithValue.EnumUtils.toLong(negotiateFlags)); // NegotiateFlags (4 bytes)

// If `omitVersion`, we skip rendering the Version, as some servers don't like it.
if (negotiateFlags.contains(NtlmNegotiateFlag.NTLMSSP_NEGOTIATE_VERSION)) {
buffer.putRawBytes(getVersion()); // Version (8 bytes)
} else if (!omitVersion) {
buffer.putUInt64(0L);
} else if (mic != null) {
buffer.putUInt64(0L); // If the MIC is present, the Version field MUST be present.
}

if (mic != null) {
buffer.putRawBytes(mic, 0, 16); // MIC (16 bytes)
}

// Payload
buffer.putRawBytes(lmResponse);
buffer.putRawBytes(ntResponse);
buffer.putRawBytes(domainName);
buffer.putRawBytes(userName);
buffer.putRawBytes(workstation);
buffer.putRawBytes(encryptedRandomSessionKey);
}

public void setMic(byte[] mic) {
this.mic = mic;
}

/**
Expand All @@ -136,16 +125,17 @@ public byte[] getVersion() {
return plainBuffer.getCompactData();
}


@Override
public String toString() {
return "NtlmAuthenticate{\n" +
" mic=" + (mic != null ? ByteArrayUtils.printHex(mic) : "[]") + ",\n" +
" lmResponse=" + ByteArrayUtils.printHex(lmResponse) + ",\n" +
" ntResponse=" + ByteArrayUtils.printHex(ntResponse) + ",\n" +
" domainName='" + NtlmFunctions.unicode(domainName) + "',\n" +
" userName='" + NtlmFunctions.unicode(userName) + "',\n" +
" workstation='" + NtlmFunctions.unicode(workstation) + "',\n" +
" encryptedRandomSessionKey=[<secret>],\n" +
'}';
" mic=" + (mic != null ? ByteArrayUtils.printHex(mic) : "[]") + ",\n" +
" lmResponse=" + ByteArrayUtils.printHex(lmResponse) + ",\n" +
" ntResponse=" + ByteArrayUtils.printHex(ntResponse) + ",\n" +
" domainName='" + NtlmFunctions.unicode(domainName) + "',\n" +
" userName='" + NtlmFunctions.unicode(userName) + "',\n" +
" workstation='" + NtlmFunctions.unicode(workstation) + "',\n" +
" encryptedRandomSessionKey=[<secret>],\n" +
'}';
}
}
4 changes: 2 additions & 2 deletions src/main/java/com/hierynomus/smbj/SmbConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ public static SmbConfig createDefaultConfig() {
public static Builder builder() {
Builder b = new Builder()
.withClientGuid(UUID.randomUUID())
.withRandomProvider(new SecureRandom())
.withSecurityProvider(getDefaultSecurityProvider())
.withSocketFactory(new ProxySocketFactory())
.withSigningRequired(false)
Expand Down Expand Up @@ -141,6 +140,7 @@ private static List<Factory.Named<Authenticator>> getDefaultAuthenticators() {

private SmbConfig() {
dialects = EnumSet.noneOf(SMB2Dialect.class);
random = new SecureRandom();
authenticators = new ArrayList<>();
}

Expand Down Expand Up @@ -281,7 +281,7 @@ public static class Builder {

Builder() {
config = new SmbConfig();
ntlmConfigBuilder = NtlmConfig.builder();
ntlmConfigBuilder = NtlmConfig.builder(config.random);
}

public Builder withRandomProvider(Random random) {
Expand Down
Loading

0 comments on commit c81367c

Please sign in to comment.