Skip to content

Commit

Permalink
GH-9794: Encode SMB domain, username & password before SmbFile
Browse files Browse the repository at this point in the history
Fixes: #9794
Issue link: #9794

The `SmbConfig.rawUrl()` method doesn't apply any URL encoding,
resulting in parts of the `domainUserPass` that may contain a `@` character to break
the URL logic in regard to determining the hostname.

* Modify `SmbConfig.getDomainUserPass(_includePassword)` to conditionally encode the variables.
Makes sure to encode the individual parts to not undesirably encode the `;` and `:` characters, breaking other logic.
* Modify `SmbConfig.rawUrl(_includePassword)` and `SmbConfig.createUri(_includePassword)`
to call the modified method with the correct `_urlEncode` variable

Signed-off-by: Jelle Smits <[email protected]>

[[email protected]: some code cleanup]

* Add author to the affected classes
* Remove redundant explicit exceptions list from the `SmbMessageHistoryTests`

**Auto-cherry-pick to `6.4.x` & `6.3.x`**

Signed-off-by: Artem Bilan <[email protected]>
  • Loading branch information
smitsjelle authored and artembilan committed Jan 28, 2025
1 parent 91f4fe4 commit 36e4012
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,8 @@

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import jcifs.DialectVersion;

Expand All @@ -34,6 +36,7 @@
* @author Prafull Kumar Soni
* @author Artem Bilan
* @author Gregory Bragg
* @author Jelle Smits
*
* @since 6.0
*/
Expand Down Expand Up @@ -163,16 +166,19 @@ public void setSmbMaxVersion(DialectVersion _smbMaxVersion) {
this.smbMaxVersion = _smbMaxVersion;
}

String getDomainUserPass(boolean _includePassword) {
String getDomainUserPass(boolean _includePassword, boolean _urlEncode) {
String domainUserPass;
String username = _urlEncode ? URLEncoder.encode(this.username, StandardCharsets.UTF_8) : this.username;
String password = _urlEncode ? URLEncoder.encode(this.password, StandardCharsets.UTF_8) : this.password;
if (StringUtils.hasText(this.domain)) {
domainUserPass = String.format("%s;%s", this.domain, this.username);
String domain = _urlEncode ? URLEncoder.encode(this.domain, StandardCharsets.UTF_8) : this.domain;
domainUserPass = String.format("%s;%s", domain, username);
}
else {
domainUserPass = this.username;
domainUserPass = username;
}
if (StringUtils.hasText(this.password)) {
domainUserPass += ":" + (_includePassword ? this.password : "********");
if (StringUtils.hasText(password)) {
domainUserPass += ":" + (_includePassword ? password : "********");
}
return domainUserPass;
}
Expand Down Expand Up @@ -211,20 +217,22 @@ public final String rawUrl() {
}

/**
* Return the url string for the share connection without encoding.
* Return the url string for the share connection without encoding
* the host and path. The {@code domainUserPass} is encoded, as
* {@link java.net.URL} requires them to be encoded otherwise its parsing fails.
* Used in the {@link SmbShare} constructor delegation.
* @param _includePassword whether password has to be masked in credentials of URL.
* @return the url string for the share connection without encoding.
* @since 6.3.8
*/
public final String rawUrl(boolean _includePassword) {
String domainUserPass = getDomainUserPass(_includePassword);
String domainUserPass = getDomainUserPass(_includePassword, true);
String path = cleanPath();
return "smb://%s@%s%s".formatted(domainUserPass, getHostPort(), path);
}

private URI createUri(boolean _includePassword) {
String domainUserPass = getDomainUserPass(_includePassword);
String domainUserPass = getDomainUserPass(_includePassword, false);
String path = cleanPath();
try {
return new URI("smb", domainUserPass, this.host, this.port, path, null, null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,8 +17,12 @@
package org.springframework.integration.smb;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Properties;

import jcifs.CIFSContext;
import jcifs.config.PropertyConfiguration;
import jcifs.context.BaseContext;
import org.junit.jupiter.api.Test;

import org.springframework.context.support.ClassPathXmlApplicationContext;
Expand All @@ -32,11 +36,12 @@
* @author Prafull Kumar Soni
* @author Artem Bilan
* @author Gregory Bragg
* @author Jelle Smits
*/
public class SmbMessageHistoryTests extends AbstractBaseTests {

@Test
public void testMessageHistory() throws URISyntaxException {
public void testMessageHistory() throws Exception {
try (ClassPathXmlApplicationContext applicationContext = getApplicationContext()) {
SourcePollingChannelAdapter adapter = applicationContext
.getBean("smbInboundChannelAdapter", SourcePollingChannelAdapter.class);
Expand All @@ -51,6 +56,12 @@ public void testMessageHistory() throws URISyntaxException {
assertThat(uri.getUserInfo()).isEqualTo("sambagu@est:sambag%uest");
assertThat(uri.getPath()).isEqualTo("/smb share/");
assertThat(uri.getRawPath()).isEqualTo("/smb%20share/");

CIFSContext context = new BaseContext(new PropertyConfiguration(new Properties()));
URL rawUrl = new URL(null, smbSessionFactory.rawUrl(true), context.getUrlHandler());
assertThat(rawUrl.getHost()).isEqualTo("localhost");
assertThat(rawUrl.getUserInfo()).isEqualTo("sambagu%40est:sambag%25uest");
assertThat(rawUrl.getPath()).isEqualTo("/smb share/");
}
}

Expand Down

0 comments on commit 36e4012

Please sign in to comment.