Skip to content

Commit

Permalink
GH-208: Allow setting of SMB min/max versions
Browse files Browse the repository at this point in the history
Fixes #208

* Updated to be able to use min/max SMB version property settings

* cleanup of formatting of file

* Updated based on review comments

* Updated readme for new functionality

* Some polishing of readme and follow current naming conventions

* Updated, missed naming convention on Javadoc

* Updated per review comments
  • Loading branch information
GregBragg authored and artembilan committed Apr 15, 2019
1 parent e91cb38 commit d4f42cb
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 20 deletions.
52 changes: 39 additions & 13 deletions spring-integration-smb/README.md
Expand Up @@ -3,7 +3,7 @@ Spring Integration SMB Support

## Introduction

This module add Spring Integration support for [Server Message Block][] (SMB).
This module adds Spring Integration support for [Server Message Block][] (SMB).

[Server Message Block]: https://en.wikipedia.org/wiki/Server_Message_Block

Expand All @@ -23,9 +23,13 @@ Put the following block into pom.xml if using Maven:

## Changes

##### Version 1.1
* Updated to use the latest version of the [JCIFS](https://github.com/codelibs/jcifs) library
* SMB2 (2.02 protocol level) support, some SMB3 support

##### Version 1.2
* Ability to set the SMB min/max versions in the `SmbSessionFactory` via configuration in the JCIFS library

## Overview

The Java CIFS Client Library has been chosen as a Java implementation for the CIFS/SMB networking protocol.
Expand All @@ -46,15 +50,37 @@ For XML configuration the `<int-smb:inbound-channel-adapter>` component is provi
There is no (yet) some SMB specific requirements for files transferring to SMB, so for XML `<int-smb:outbound-channel-adapter>` component we simply reuse an existing `FileTransferringMessageHandler`.
In case of Java configuration that `FileTransferringMessageHandler` should be supplied with the `SmbSessionFactory` (or `SmbRemoteFileTemplate`).

@ServiceActivator(inputChannel = "storeToSmb")
@Bean
public MessageHandler smbMessageHandler(SmbSessionFactory smbSessionFactory) {
FileTransferringMessageHandler<SmbFile> handler =
new FileTransferringMessageHandler<>(smbSessionFactory);
handler.setRemoteDirectoryExpression(
new LiteralExpression("remote-target-dir"));
handler.setFileNameGenerator(m ->
m.getHeaders().get(FileHeaders.FILENAME, String.class) + ".test");
handler.setAutoCreateDirectory(true);
return handler;
}
````java
@ServiceActivator(inputChannel = "storeToSmb")
@Bean
public MessageHandler smbMessageHandler(SmbSessionFactory smbSessionFactory) {
FileTransferringMessageHandler<SmbFile> handler =
new FileTransferringMessageHandler<>(smbSessionFactory);
handler.setRemoteDirectoryExpression(
new LiteralExpression("remote-target-dir"));
handler.setFileNameGenerator(m ->
m.getHeaders().get(FileHeaders.FILENAME, String.class) + ".test");
handler.setAutoCreateDirectory(true);
return handler;
}
````

### Setting SMB Protocol Min/Max Versions

Example: To set a minimum version of SMB 2.1 and a maximum version of SMB 3.1.1

````java
@Bean
public SmbSessionFactory smbSessionFactory() {
SmbSessionFactory smbSession = new SmbSessionFactory();
smbSession.setHost("myHost");
smbSession.setPort(445);
smbSession.setDomain("myDomain");
smbSession.setUsername("myUser");
smbSession.setPassword("myPassword");
smbSession.setShareAndDir("myShareAndDir");
smbSession.setSmbMinVersion(DialectVersion.SMB210);
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
return smbSession;
}
````
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 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 @@ -22,6 +22,8 @@
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import jcifs.DialectVersion;

/**
* Data holder class for a SMB share configuration.
*
Expand All @@ -31,8 +33,7 @@
* @author Markus Spann
* @author Prafull Kumar Soni
* @author Artem Bilan
*
* @since 1.0
* @author Gregory Bragg
*/
public class SmbConfig {

Expand All @@ -52,6 +53,18 @@ public class SmbConfig {

private boolean useTempFile = false;

/**
* Defaults to and follows the jCIFS library default of 'SMB1'
* @since 1.2
*/
private DialectVersion smbMinVersion = DialectVersion.SMB1;

/**
* Defaults to and follows the jCIFS library default of 'SMB210'
* @since 1.2
*/
private DialectVersion smbMaxVersion = DialectVersion.SMB210;

public SmbConfig() {
}

Expand Down Expand Up @@ -134,6 +147,46 @@ public boolean isUseTempFile() {
return this.useTempFile;
}

/**
* Gets the desired minimum SMB version value for what the Windows server will allow
* during protocol transport negotiation.
* @return one of SMB1, SMB202, SMB210, SMB300, SMB302 or SMB311
* @since 1.2
*/
public DialectVersion getSmbMinVersion() {
return this.smbMinVersion;
}

/**
* Sets the desired minimum SMB version value for what the Windows server will allow
* during protocol transport negotiation.
* @param _smbMinVersion one of SMB1, SMB202, SMB210, SMB300, SMB302 or SMB311
* @since 1.2
*/
public void setSmbMinVersion(DialectVersion _smbMinVersion) {
this.smbMinVersion = _smbMinVersion;
}

/**
* Gets the desired maximum SMB version value for what the Windows server will allow
* during protocol transport negotiation.
* @return one of SMB1, SMB202, SMB210, SMB300, SMB302 or SMB311
* @since 1.2
*/
public DialectVersion getSmbMaxVersion() {
return this.smbMaxVersion;
}

/**
* Sets the desired maximum SMB version value for what the Windows server will allow
* during protocol transport negotiation.
* @param _smbMaxVersion one of SMB1, SMB202, SMB210, SMB300, SMB302 or SMB311
* @since 1.2
*/
public void setSmbMaxVersion(DialectVersion _smbMaxVersion) {
this.smbMaxVersion = _smbMaxVersion;
}

String getDomainUserPass(boolean _includePassword) {
String domainUserPass;
if (StringUtils.hasText(this.domain)) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 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,6 +17,7 @@
package org.springframework.integration.smb.session;

import java.io.IOException;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand All @@ -29,7 +30,7 @@
* The SMB session factory.
*
* @author Markus Spann
* @since 1.0
* @author Gregory Bragg
*/
public class SmbSessionFactory extends SmbConfig implements SessionFactory<SmbFile> {

Expand All @@ -39,6 +40,7 @@ public SmbSessionFactory() {
logger.debug("New " + getClass().getName() + " created.");
}

@Override
public final SmbSession getSession() {
try {
return createSession();
Expand All @@ -49,7 +51,11 @@ public final SmbSession getSession() {
}

protected SmbSession createSession() throws IOException {
SmbShare smbShare = new SmbShare(this);
Properties props = new Properties();
props.setProperty("jcifs.smb.client.minVersion", this.getSmbMinVersion().name());
props.setProperty("jcifs.smb.client.maxVersion", this.getSmbMaxVersion().name());

SmbShare smbShare = new SmbShare(this, props);
smbShare.setReplaceFile(isReplaceFile());
smbShare.setUseTempFile(isUseTempFile());

Expand Down
Expand Up @@ -17,6 +17,7 @@
package org.springframework.integration.smb.session;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.logging.Log;
Expand All @@ -26,6 +27,8 @@
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import jcifs.config.PropertyConfiguration;
import jcifs.context.BaseContext;
import jcifs.context.SingletonContext;
import jcifs.smb.NtlmPasswordAuthenticator;
import jcifs.smb.SmbException;
Expand Down Expand Up @@ -55,12 +58,36 @@ public SmbShare(String url) throws IOException {
super(StringUtils.cleanPath(url));
}

/**
* Initializes the jCIFS library with default properties.
* @param _smbConfig the SMB share configuration
* @throws IOException if an invalid SMB URL was constructed by jCIFS
* @since 1.1
*/
public SmbShare(SmbConfig _smbConfig) throws IOException {
super(StringUtils.cleanPath(_smbConfig.validate().getUrl()),
SingletonContext.getInstance().withCredentials(new NtlmPasswordAuthenticator(
SingletonContext.getInstance().withCredentials(
new NtlmPasswordAuthenticator(
_smbConfig.getDomain(), _smbConfig.getUsername(), _smbConfig.getPassword())));
}

/**
* Initializes the jCIFS library with custom properties such as
* 'jcifs.smb.client.minVersion' and 'jcifs.smb.client.maxVersion'
* for setting the minimum/maximum SMB supported versions.
* @param _smbConfig the SMB share configuration
* @param _props the custom property set for jCIFS to initialize
* @throws IOException if an invalid property was set or an invalid SMB URL was constructed by jCIFS
* @since 1.2
*/
public SmbShare(SmbConfig _smbConfig, Properties _props) throws IOException {
super(StringUtils.cleanPath(_smbConfig.validate().getUrl()),
new BaseContext(
new PropertyConfiguration(_props)).withCredentials(
new NtlmPasswordAuthenticator(
_smbConfig.getDomain(), _smbConfig.getUsername(), _smbConfig.getPassword())));
}

public void init() throws NestedIOException {
boolean canRead = false;
try {
Expand Down
Expand Up @@ -19,9 +19,11 @@
import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.util.Properties;

import org.junit.Test;

import jcifs.DialectVersion;
import jcifs.smb.SmbFile;

/**
Expand Down Expand Up @@ -134,4 +136,69 @@ public void testCreateSmbFileObjectWithMissingTrailingSlash3() throws IOExceptio
smbSession.close();
}

@Test
public void testCreateSmbFileObjectWithSmb3Versions1() throws IOException {
Properties props = new Properties();
SmbConfig config = new SmbConfig();

config.setHost("myshare");
config.setPort(445);
config.setShareAndDir("shared/");
config.setSmbMinVersion(DialectVersion.SMB300);
config.setSmbMaxVersion(DialectVersion.SMB311);

props.setProperty("jcifs.smb.client.minVersion", config.getSmbMinVersion().name());
props.setProperty("jcifs.smb.client.maxVersion", config.getSmbMaxVersion().name());

SmbShare smbShare = new SmbShare(config, props);
SmbSession smbSession = new SmbSession(smbShare);

SmbFile smbFile = smbSession.createSmbFileObject("smb://myshare\\blubba");
assertEquals("smb://myshare/blubba", smbFile.getPath());
smbSession.close();
}

@Test
public void testCreateSmbFileObjectWithSmb3Versions2() throws IOException {
Properties props = new Properties();
SmbConfig config = new SmbConfig();

config.setHost("myshare");
config.setPort(445);
config.setShareAndDir("shared/");
config.setSmbMinVersion(DialectVersion.SMB302);
config.setSmbMaxVersion(DialectVersion.SMB311);

props.setProperty("jcifs.smb.client.minVersion", config.getSmbMinVersion().name());
props.setProperty("jcifs.smb.client.maxVersion", config.getSmbMaxVersion().name());

SmbShare smbShare = new SmbShare(config, props);
SmbSession smbSession = new SmbSession(smbShare);

SmbFile smbFile = smbSession.createSmbFileObject("smb://myshare\\blubba");
assertEquals("smb://myshare/blubba", smbFile.getPath());
smbSession.close();
}

@Test
public void testCreateSmbFileObjectWithSmb3Versions3() throws IOException {
Properties props = new Properties();
SmbConfig config = new SmbConfig();

config.setHost("myshare");
config.setPort(445);
config.setShareAndDir("shared/");
config.setSmbMinVersion(DialectVersion.SMB311);
config.setSmbMaxVersion(DialectVersion.SMB311);

props.setProperty("jcifs.smb.client.minVersion", config.getSmbMinVersion().name());
props.setProperty("jcifs.smb.client.maxVersion", config.getSmbMaxVersion().name());

SmbShare smbShare = new SmbShare(config, props);
SmbSession smbSession = new SmbSession(smbShare);

SmbFile smbFile = smbSession.createSmbFileObject("smb://myshare\\blubba");
assertEquals("smb://myshare/blubba", smbFile.getPath());
smbSession.close();
}
}

0 comments on commit d4f42cb

Please sign in to comment.