Skip to content

Instantly share code, notes, and snippets.

@dovidkopel
Last active January 3, 2024 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dovidkopel/9eca457e670fb9272ad7 to your computer and use it in GitHub Desktop.
Save dovidkopel/9eca457e670fb9272ad7 to your computer and use it in GitHub Desktop.
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.core.DeviceContext;
import org.alfresco.jlan.server.filesys.FileExistsException;
import org.alfresco.jlan.server.filesys.FileName;
import org.alfresco.jlan.server.filesys.FileOpenParams;
import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.jlan.smb.server.disk.JavaFileDiskDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
/**
* Created by dkopel on 3/13/16.
*/
@Component
public class InMemoryFileDriver extends JavaFileDiskDriver {
private Logger logger = LoggerFactory.getLogger(getClass());
private NetworkFile f;
@Override
public NetworkFile createFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException {
DeviceContext ctx = tree.getContext();
String fname = FileName.buildPath(ctx.getDeviceName(), params.getPath(), (String)null, File.separatorChar);
File file = new File(fname);
logger.info("User {} created a new file called {}.", sess.getClientInformation().getUserName(), fname);
if(file.exists()) {
throw new FileExistsException();
} else {
InMemoryNetworkFile netFile = new InMemoryNetworkFile(fname);
netFile.setGrantedAccess(2);
netFile.setAllowedAccess(2);
netFile.setFullName(params.getPath());
return netFile;
}
}
@Override
public int writeFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufoff, int siz, long fileoff) throws IOException {
logger.info("Write request to file {} with data {} {}.", file.getFullName(), siz);
return super.writeFile(sess, tree, file, buf, bufoff, siz, fileoff);
}
@Override
public void closeFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws IOException {
super.closeFile(sess, tree, file);
logger.info("Close file {}.", file.getFullName(), sess.getClientInformation().getUserName());
// Over here if we had a write we can now transfer the contents of the file into our system!
}
}
import org.alfresco.jlan.server.filesys.NetworkFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Created by dkopel on 3/15/16.
*/
public class InMemoryNetworkFile extends NetworkFile {
private ByteArrayOutputStream out = new ByteArrayOutputStream();
private byte[] data;
private AtomicBoolean opened = new AtomicBoolean(false);
private Logger logger = LoggerFactory.getLogger(getClass());
public InMemoryNetworkFile(int fid) {
super(fid);
}
public InMemoryNetworkFile(int fid, int did) {
super(fid, did);
}
public InMemoryNetworkFile(int fid, int stid, int did) {
super(fid, stid, did);
}
public InMemoryNetworkFile(String name) {
super(name);
}
@Override
public void openFile(boolean b) throws IOException {
opened.set(b);
}
@Override
public int readFile(byte[] bytes, int i, int i1, long l) throws IOException {
return 0;
}
@Override
public void writeFile(byte[] bytes, int len, int pos, long offset) throws IOException {
logger.debug("Bytes Size: {}, Length: {}, Position: {}, Offset: {}", bytes.length, len, pos, offset);
out.write(bytes, pos, len);
logger.debug("Data is now {} bytes", out.size());
}
@Override
public long seekFile(long l, int i) throws IOException {
return 0;
}
@Override
public void flushFile() throws IOException {
logger.info("Flushed!");
}
@Override
public void truncateFile(long l) throws IOException {
out.reset();
}
@Override
public void closeFile() throws IOException {
opened.set(false);
out.close();
data = out.toByteArray();
}
public byte[] getData() {
return data;
}
}
import org.alfresco.jlan.debug.DebugConfigSection;
import org.alfresco.jlan.netbios.server.NetBIOSNameServer;
import org.alfresco.jlan.server.NetworkServer;
import org.alfresco.jlan.server.auth.EnterpriseCifsAuthenticator;
import org.alfresco.jlan.server.auth.acl.DefaultAccessControlManager;
import org.alfresco.jlan.server.config.CoreServerConfigSection;
import org.alfresco.jlan.server.config.GlobalConfigSection;
import org.alfresco.jlan.server.config.InvalidConfigurationException;
import org.alfresco.jlan.server.config.SecurityConfigSection;
import org.alfresco.jlan.server.config.ServerConfiguration;
import org.alfresco.jlan.server.core.DeviceContextException;
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
import org.alfresco.jlan.server.filesys.SrvDiskInfo;
import org.alfresco.jlan.smb.server.CIFSConfigSection;
import org.alfresco.jlan.smb.server.SMBServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.extensions.config.element.GenericConfigElement;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* Created by dkopel on 3/13/16.
*/
@Service
public class SmbService {
private BeanFactory beanFactory;
private UserAuthenticationService userAuthenticationService;
@Value("${smb.hostname}")
private String hostname;
@Value("${smb.domain}")
private String domain;
@Value("${smb.share}")
private String share;
@Value("${smb.broadcastMask}")
private String broadcastMask;
private Logger LOGGER = LoggerFactory.getLogger(getClass());
@Autowired
public SmbService setUserAuthenticationService(UserAuthenticationService userAuthenticationService) {
this.userAuthenticationService = userAuthenticationService;
return this;
}
@Autowired
public SmbService setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
return this;
}
@PostConstruct
public void init() {
try {
ServerConfiguration cfg = new DarkPointServerConfig();
NetBIOSNameServer netBIOSNameServer = new NetBIOSNameServer(cfg);
cfg.addServer(netBIOSNameServer);
SMBServer smbServer = new SMBServer(cfg);
cfg.addServer(smbServer);
for (int i = 0; i < cfg.numberOfServers(); i++) {
NetworkServer server = cfg.getServer(i);
server.startServer();
}
} catch (Exception e) {
LOGGER.error("Something went terribly wrong with the samba server!");
e.printStackTrace();
}
}
class ServerConfig extends ServerConfiguration {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final int DefaultThreadPoolInit = 1;
private static final int DefaultThreadPoolMax = 1;
private final int[] DefaultMemoryPoolBufSizes = { 256, 4096, 16384, 66000 };
private final int[] DefaultMemoryPoolInitAlloc = { 20, 20, 5, 5 };
private final int[] DefaultMemoryPoolMaxAlloc = { 100, 50, 50, 50 };
public ServerConfig() throws InvalidConfigurationException, DeviceContextException {
super(hostname);
setServerName(hostname);
// DEBUG
DebugConfigSection debugConfig = new DebugConfigSection(this);
final GenericConfigElement debugConfigElement = new GenericConfigElement("output");
final GenericConfigElement logLevelConfigElement = new GenericConfigElement("logLevel");
logLevelConfigElement.setValue("Info");
debugConfig.setDebug("org.alfresco.jlan.debug.ConsoleDebug", debugConfigElement);
// CORE
CoreServerConfigSection coreConfig = new CoreServerConfigSection(this);
coreConfig.setMemoryPool( DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc);
coreConfig.setThreadPool(DefaultThreadPoolInit, DefaultThreadPoolMax);
coreConfig.getThreadPool().setDebug(false);
// GLOBAL
GlobalConfigSection globalConfig = new GlobalConfigSection(this);
// SECURITY
final SecurityConfigSection secConfig = new SecurityConfigSection(this);
secConfig.setUsersInterface(
"connector.smb.UsersInterface",
new GenericConfigElement("")
);
this.addConfigSection(secConfig);
DefaultAccessControlManager accessControlManager = new DefaultAccessControlManager();
accessControlManager.setDebug(false);
// SHARES
FilesystemsConfigSection filesysConfig = new FilesystemsConfigSection(this);
DiskInterface diskInterface = beanFactory.getBean(InMemoryFileDriver.class);
final GenericConfigElement driverConfig = new GenericConfigElement("driver");
final GenericConfigElement localPathConfig = new GenericConfigElement("LocalPath");
localPathConfig.setValue("/tmp");
driverConfig.addChild(localPathConfig);
DiskDeviceContext diskDeviceContext = (DiskDeviceContext) diskInterface.createContext(share, driverConfig);
diskDeviceContext.setShareName(share);
diskDeviceContext.setConfigurationParameters(driverConfig);
diskDeviceContext.enableChangeHandler(false);
diskDeviceContext.setDiskInformation(new SrvDiskInfo(2560000, 64, 512, 2304000));// Default to a 80Gb sized disk with 90% free space
DiskSharedDevice diskDev = new DiskSharedDevice(share, diskInterface, diskDeviceContext);
diskDev.setConfiguration(this);
diskDev.setAccessControlList(secConfig.getGlobalAccessControls());
diskDeviceContext.startFilesystem(diskDev);
filesysConfig.addShare(diskDev);
// SMB
CIFSConfigSection cifsConfig = new CIFSConfigSection(this);
if(broadcastMask != null && broadcastMask.length() > 0) {
cifsConfig.setBroadcastMask(broadcastMask);
}
if(domain != null && domain.length() > 0) {
cifsConfig.setDomainName(domain);
}
cifsConfig.setServerName(hostname);
cifsConfig.setHostAnnounceInterval(5);
cifsConfig.setHostAnnouncer(true);
cifsConfig.setWin32NetBIOS(true);
cifsConfig.setWin32HostAnnounceInterval(5);
cifsConfig.setTcpipSMB(true);
final EnterpriseCifsAuthenticator authenticator = new EnterpriseCifsAuthenticator();
authenticator.setDebug(true);
authenticator.setAllowGuest(false);
authenticator.setAccessMode(EnterpriseCifsAuthenticator.NTLM2);
authenticator.initialize(this, new GenericConfigElement("authenticator"));
cifsConfig.setAuthenticator(authenticator);
// For debugging SMB in depth
//cifsConfig.setSessionDebugFlags(-1);
}
}
}
import com.sun.xml.internal.fastinfoset.util.CharArray;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.alfresco.jlan.server.auth.UserAccount;
import org.alfresco.jlan.server.auth.UsersInterface;
import org.alfresco.jlan.server.config.InvalidConfigurationException;
import org.alfresco.jlan.server.config.ServerConfiguration;
import org.alfresco.jlan.util.HexDump;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.extensions.config.ConfigElement;
import java.security.Security;
/**
* Created by dkopel on 3/15/16.
*/
public class UsersInterface implements UsersInterface {
private Logger logger = LoggerFactory.getLogger(getClass());
private UserAuthenticationService userAuthenticationService;
public UsersInterface() {
Security.addProvider(new BouncyCastleProvider());
userAuthenticationService = BeanAccessor.getBean(UserAuthenticationService.class);
}
@Override
public void initializeUsers(ServerConfiguration serverConfiguration, ConfigElement configElement) throws InvalidConfigurationException {
}
@Override
public UserAccount getUserAccount(String s) {
MD4User u = findAccount(s);
if(u != null) {
logger.info("User exists with the username {}", s);
logger.info("MD4 Password {}", HexDump.hexString(u.getPasswordMD4()));
UserAccount us = new UserAccount(
u.getUsername(),
null
);
try {
us.setMD4Password(Hex.decodeHex(u.getPasswordMD4String().toCharArray()));
} catch (DecoderException e) {
e.printStackTrace();
}
return us;
} else {
logger.info("User does not exist with the username {}", s);
return null;
}
}
public MD4User findAccount(String s) {
return userAuthenticationService.getUser(s);
}
interface UserAuthenticationService {
boolean authenticate(String username, String password);
MD4User getUser(String username);
}
interface MD4User extends UserDetails {
byte[] getPasswordMD4();
String getPasswordMD4String();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment