/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.filesys.server.config;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.Provider;
import java.security.Security;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TimeZone;
import net.sf.acegisecurity.AuthenticationManager;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigLookupContext;
import org.alfresco.config.ConfigSource;
import org.alfresco.config.source.UrlConfigSource;
import org.alfresco.config.xml.XMLConfigService;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.ftp.FTPPath;
import org.alfresco.filesys.ftp.InvalidPathException;
import org.alfresco.filesys.netbios.NetBIOSName;
import org.alfresco.filesys.netbios.NetBIOSNameList;
import org.alfresco.filesys.netbios.NetBIOSSession;
import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
import org.alfresco.filesys.netbios.win32.Win32NetBIOS;
import org.alfresco.filesys.server.NetworkServer;
import org.alfresco.filesys.server.NetworkServerList;
import org.alfresco.filesys.server.auth.LocalAuthenticator;
import org.alfresco.filesys.server.auth.SrvAuthenticator;
import org.alfresco.filesys.server.auth.UserAccount;
import org.alfresco.filesys.server.auth.UserAccountList;
import org.alfresco.filesys.server.auth.acl.ACLParseException;
import org.alfresco.filesys.server.auth.acl.AccessControl;
import org.alfresco.filesys.server.auth.acl.AccessControlList;
import org.alfresco.filesys.server.auth.acl.AccessControlManager;
import org.alfresco.filesys.server.auth.acl.AccessControlParser;
import org.alfresco.filesys.server.auth.acl.DefaultAccessControlManager;
import org.alfresco.filesys.server.auth.acl.InvalidACLTypeException;
import org.alfresco.filesys.server.core.DeviceContext;
import org.alfresco.filesys.server.core.DeviceContextException;
import org.alfresco.filesys.server.core.ShareMapper;
import org.alfresco.filesys.server.core.ShareType;
import org.alfresco.filesys.server.core.SharedDevice;
import org.alfresco.filesys.server.core.SharedDeviceList;
import org.alfresco.filesys.server.filesys.DefaultShareMapper;
import org.alfresco.filesys.server.filesys.DiskDeviceContext;
import org.alfresco.filesys.server.filesys.DiskInterface;
import org.alfresco.filesys.server.filesys.DiskSharedDevice;
import org.alfresco.filesys.server.filesys.HomeShareMapper;
import org.alfresco.filesys.smb.Dialect;
import org.alfresco.filesys.smb.DialectSelector;
import org.alfresco.filesys.smb.ServerType;
import org.alfresco.filesys.util.IPAddress;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* Provides the configuration parameters for the network file servers.
*
* @author Gary K. Spencer
*/
public class ServerConfiguration
{
// Debug logging
private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
// Filesystem configuration constants
private static final String ConfigArea = "file-servers";
private static final String ConfigCIFS = "CIFS Server";
private static final String ConfigFTP = "FTP Server";
private static final String ConfigFilesystems = "Filesystems";
private static final String ConfigSecurity = "Filesystem Security";
// Server configuration bean name
public static final String SERVER_CONFIGURATION = "fileServerConfiguration";
// SMB/CIFS session debug type strings
//
// Must match the bit mask order
private static final String m_sessDbgStr[] = { "NETBIOS", "STATE", "NEGOTIATE", "TREE", "SEARCH", "INFO", "FILE",
"FILEIO", "TRANSACT", "ECHO", "ERROR", "IPC", "LOCK", "PKTTYPE", "DCERPC", "STATECACHE", "NOTIFY",
"STREAMS", "SOCKET" };
// FTP server debug type strings
private static final String m_ftpDebugStr[] = { "STATE", "SEARCH", "INFO", "FILE", "FILEIO", "ERROR", "PKTTYPE",
"TIMING", "DATAPORT", "DIRECTORY" };
// Default FTP server port
private static final int DefaultFTPServerPort = 21;
// Default FTP anonymous account name
private static final String DefaultFTPAnonymousAccount = "anonymous";
// Platform types
public enum PlatformType
{
Unknown, WINDOWS, LINUX, SOLARIS, MACOSX
};
// Token name to substitute current server name into the CIFS server name
private static final String TokenLocalName = "${localname}";
// Acegi authentication manager
private AuthenticationManager acegiAuthMgr;
// Path to configuration file
private String configLocation;
/** the device to connect use */
private DiskInterface diskInterface;
// Runtime platform type
private PlatformType m_platform = PlatformType.Unknown;
// Main server enable flags, to enable SMB, FTP and/or NFS server components
private boolean m_smbEnable = true;
private boolean m_ftpEnable = true;
// Server name
private String m_name;
// Server type, used by the host announcer
private int m_srvType = ServerType.WorkStation + ServerType.Server + ServerType.NTServer;
// Active server list
private NetworkServerList m_serverList;
// Server comment
private String m_comment;
// Server domain
private String m_domain;
// Network broadcast mask string
private String m_broadcast;
// Announce the server to network neighborhood, announcement interval in
// minutes
private boolean m_announce;
private int m_announceInterval;
// Default SMB dialects to enable
private DialectSelector m_dialects;
// List of shared devices
private SharedDeviceList m_shareList;
// Authenticator, used to authenticate users and share connections.
private SrvAuthenticator m_authenticator;
// Share mapper
private ShareMapper m_shareMapper;
// Access control manager
private AccessControlManager m_aclManager;
// Global access control list, applied to all shares that do not have access
// controls
private AccessControlList m_globalACLs;
private boolean m_nbDebug = false;
private boolean m_announceDebug = false;
// Default session debugging setting
private int m_sessDebug;
// Flags to indicate if NetBIOS, native TCP/IP SMB and/or Win32 NetBIOS
// should be enabled
private boolean m_netBIOSEnable = true;
private boolean m_tcpSMBEnable = false;
private boolean m_win32NBEnable = false;
// Address to bind the SMB server to, if null all local addresses are used
private InetAddress m_smbBindAddress;
// Address to bind the NetBIOS name server to, if null all addresses are
// used
private InetAddress m_nbBindAddress;
// WINS servers
private InetAddress m_winsPrimary;
private InetAddress m_winsSecondary;
// User account list
private UserAccountList m_userList;
// Enable/disable Macintosh extension SMBs
private boolean m_macExtensions;
// --------------------------------------------------------------------------------
// Win32 NetBIOS configuration
//
// Server name to register under Win32 NetBIOS, if not set the main server
// name is used
private String m_win32NBName;
// LANA to be used for Win32 NetBIOS, if not specified the first available
// is used
private int m_win32NBLANA = -1;
// Send out host announcements via the Win32 NetBIOS interface
private boolean m_win32NBAnnounce = false;
private int m_win32NBAnnounceInterval;
// Use Winsock NetBIOS interface if true, else use the Netbios() API interface
private boolean m_win32NBUseWinsock = true;
// --------------------------------------------------------------------------------
// FTP specific configuration parameters
//
// Bind address and FTP server port.
private InetAddress m_ftpBindAddress;
private int m_ftpPort = DefaultFTPServerPort;
// Allow anonymous FTP access and anonymous FTP account name
private boolean m_ftpAllowAnonymous;
private String m_ftpAnonymousAccount;
// FTP root path, if not specified defaults to listing all shares as the root
private String m_ftpRootPath;
// FTP server debug flags
private int m_ftpDebug;
// --------------------------------------------------------------------------------
// Global server configuration
//
// Timezone name and offset from UTC in minutes
private String m_timeZone;
private int m_tzOffset;
// JCE provider class name
private String m_jceProviderClass;
// Local server name and domain/workgroup name
private String m_localName;
private String m_localDomain;
/** flag indicating successful initialisation */
private boolean initialised;
// Main authentication service, public API
private AuthenticationService authenticationService;
// Authentication component, for internal functions
private AuthenticationComponent m_authComponent;
// Various services
private NodeService m_nodeService;
private PersonService m_personService;
private TransactionService m_transactionService;
/**
* Class constructor
*
* @param authMgr AuthenticationManager
* @param authenticationService AuthenticationService
* @param authenticationComponent AuthenticationComponent
* @param nodeService NodeService
* @param personServce PersonService
* @param transactionService TransactionService
* @param configPath String
* @param diskInterface DiskInterface
*/
public ServerConfiguration(AuthenticationManager authMgr, AuthenticationService authenticationService,
AuthenticationComponent authComponent, NodeService nodeService, PersonService personService,
TransactionService transactionService, String configPath, DiskInterface diskInterface)
{
// Save details
this.diskInterface = diskInterface;
this.acegiAuthMgr = authMgr;
this.authenticationService = authenticationService;
this.configLocation = configPath;
m_authComponent = authComponent;
m_nodeService = nodeService;
m_personService = personService;
m_transactionService = transactionService;
// Allocate the shared device list
m_shareList = new SharedDeviceList();
// Allocate the SMB dialect selector, and initialize using the default
// list of dialects
m_dialects = new DialectSelector();
m_dialects.AddDialect(Dialect.DOSLanMan1);
m_dialects.AddDialect(Dialect.DOSLanMan2);
m_dialects.AddDialect(Dialect.LanMan1);
m_dialects.AddDialect(Dialect.LanMan2);
m_dialects.AddDialect(Dialect.LanMan2_1);
m_dialects.AddDialect(Dialect.NT);
// Use the local authenticator, that allows locally defined users to connect to the
// server
setAuthenticator(new LocalAuthenticator(), null, true);
// Use the default share mapper
m_shareMapper = new DefaultShareMapper();
try
{
m_shareMapper.initializeMapper(this, null);
}
catch (InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException("Failed to initialise share mapper", ex);
}
// Set the default access control manager
m_aclManager = new DefaultAccessControlManager();
m_aclManager.initialize(this, null);
// Use the default timezone
try
{
setTimeZone(TimeZone.getDefault().getID());
}
catch (Exception ex)
{
throw new AlfrescoRuntimeException("Failed to set timezone", ex);
}
// Allocate the active server list
m_serverList = new NetworkServerList();
}
/**
* @return Returns true if the configuration was fully initialised
*/
public boolean isInitialised()
{
return initialised;
}
/**
* Initialize the configuration using the configuration service
*/
public void init()
{
initialised = false;
// Create the configuration source
ConfigSource configSource = new UrlConfigSource(configLocation);
XMLConfigService xmlConfigService = new XMLConfigService(configSource);
xmlConfigService.init();
// Create the configuration context
ConfigLookupContext configCtx = new ConfigLookupContext(ConfigArea);
// Set the platform type
determinePlatformType();
try
{
// Process the CIFS server configuration
Config config = xmlConfigService.getConfig(ConfigCIFS, configCtx);
processCIFSServerConfig(config);
// Process the FTP server configuration
config = xmlConfigService.getConfig(ConfigFTP, configCtx);
processFTPServerConfig(config);
// Process the security configuration
config = xmlConfigService.getConfig(ConfigSecurity, configCtx);
processSecurityConfig(config);
// Process the filesystems configuration
config = xmlConfigService.getConfig(ConfigFilesystems, configCtx);
processFilesystemsConfig(config);
// Successful initialisation
initialised = true;
}
catch (UnsatisfiedLinkError ex)
{
// Error accessing the Win32NetBIOS DLL code
logger.error("Error accessing Win32 NetBIOS, check DLL is on the path");
// Disable the CIFS server
setNetBIOSSMB(false);
setTcpipSMB(false);
setWin32NetBIOS(false);
setSMBServerEnabled(false);
}
catch (Throwable ex)
{
// Configuration error
logger.error("CIFS server configuration error, " + ex.getMessage(), ex);
// Disable the CIFS server
setNetBIOSSMB(false);
setTcpipSMB(false);
setWin32NetBIOS(false);
setSMBServerEnabled(false);
}
}
/**
* Determine the platform type
*/
private final void determinePlatformType()
{
// Get the operating system type
String osName = System.getProperty("os.name");
if (osName.startsWith("Windows"))
m_platform = PlatformType.WINDOWS;
else if (osName.equalsIgnoreCase("Linux"))
m_platform = PlatformType.LINUX;
else if (osName.startsWith("Mac OS X"))
m_platform = PlatformType.MACOSX;
else if (osName.startsWith("Solaris"))
m_platform = PlatformType.SOLARIS;
}
/**
* Return the platform type
*
* @return PlatformType
*/
public final PlatformType getPlatformType()
{
return m_platform;
}
/**
* Process the CIFS server configuration
*
* @param config Config
*/
private final void processCIFSServerConfig(Config config)
{
// If the configuration section is not valid then CIFS is disabled
if ( config == null || config.getConfigElements().isEmpty())
{
setSMBServerEnabled(false);
return;
}
// Get the network broadcast address
//
// Note: We need to set this first as the call to getLocalDomainName() may use a NetBIOS
// name lookup, so the broadcast mask must be set before then.
ConfigElement elem = config.getConfigElement("broadcast");
if (elem != null)
{
// Check if the broadcast mask is a valid numeric IP address
if (IPAddress.isNumericAddress(elem.getValue()) == false)
throw new AlfrescoRuntimeException("Invalid broadcast mask, must be n.n.n.n format");
// Set the network broadcast mask
setBroadcastMask(elem.getValue());
}
// Get the host configuration
elem = config.getConfigElement("host");
if (elem == null)
throw new AlfrescoRuntimeException("CIFS server host settings not specified");
String hostName = elem.getAttribute("name");
if (hostName == null || hostName.length() == 0)
throw new AlfrescoRuntimeException("Host name not specified or invalid");
// Check if the host name contains the local name token
int pos = hostName.indexOf(TokenLocalName);
if (pos != -1)
{
// Get the local server name
String srvName = getLocalServerName(true);
// Rebuild the host name substituting the token with the local server name
StringBuilder hostStr = new StringBuilder();
hostStr.append(hostName.substring(0, pos));
hostStr.append(srvName);
pos += TokenLocalName.length();
if (pos < hostName.length())
hostStr.append(hostName.substring(pos));
hostName = hostStr.toString();
// Make sure the CIFS server name does not match the local server name
if (hostName.equals(srvName))
throw new AlfrescoRuntimeException("CIFS server name must be unique");
}
// Set the CIFS server name
setServerName(hostName.toUpperCase());
// Get the domain/workgroup name
String domain = elem.getAttribute("domain");
if (domain != null && domain.length() > 0)
{
// Set the domain/workgroup name
setDomainName(domain.toUpperCase());
}
else
{
// Get the local domain/workgroup name
setDomainName(getLocalDomainName());
}
// Check for a server comment
elem = config.getConfigElement("comment");
if (elem != null)
setComment(elem.getValue());
// Check for a bind address
elem = config.getConfigElement("bindto");
if (elem != null)
{
// Validate the bind address
String bindText = elem.getValue();
try
{
// Check the bind address
InetAddress bindAddr = InetAddress.getByName(bindText);
// Set the bind address for the server
setSMBBindAddress(bindAddr);
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid CIFS server bind address");
}
}
// Check if the host announcer should be enabled
elem = config.getConfigElement("hostAnnounce");
if (elem != null)
{
// Check for an announcement interval
String interval = elem.getAttribute("interval");
if (interval != null && interval.length() > 0)
{
try
{
setHostAnnounceInterval(Integer.parseInt(interval));
}
catch (NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid host announcement interval");
}
}
// Check if the domain name has been set, this is required if the
// host announcer is enabled
if (getDomainName() == null)
throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
// Enable host announcement
setHostAnnouncer(true);
}
// Check if NetBIOS SMB is enabled
elem = config.getConfigElement("netBIOSSMB");
if (elem != null)
{
// Check if NetBIOS over TCP/IP is enabled for the current platform
String platformsStr = elem.getAttribute("platforms");
boolean platformOK = false;
if (platformsStr != null)
{
// Parse the list of platforms that NetBIOS over TCP/IP is to be enabled for and
// check if the current platform is included
EnumSet enabledPlatforms = parsePlatformString(platformsStr);
if (enabledPlatforms.contains(getPlatformType()))
platformOK = true;
}
else
{
// No restriction on platforms
platformOK = true;
}
// Check if the broadcast mask has been specified
if (getBroadcastMask() == null)
throw new AlfrescoRuntimeException("Network broadcast mask not specified");
// Enable the NetBIOS SMB support, if enabled for this platform
setNetBIOSSMB(platformOK);
// Check for a bind address
String bindto = elem.getAttribute("bindto");
if (bindto != null && bindto.length() > 0)
{
// Validate the bind address
try
{
// Check the bind address
InetAddress bindAddr = InetAddress.getByName(bindto);
// Set the bind address for the NetBIOS name server
setNetBIOSBindAddress(bindAddr);
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid NetBIOS bind address");
}
}
else if (hasSMBBindAddress())
{
// Use the SMB bind address for the NetBIOS name server
setNetBIOSBindAddress(getSMBBindAddress());
}
}
else
{
// Disable NetBIOS SMB support
setNetBIOSSMB(false);
}
// Check if TCP/IP SMB is enabled
elem = config.getConfigElement("tcpipSMB");
if (elem != null)
{
// Check if native SMB is enabled for the current platform
String platformsStr = elem.getAttribute("platforms");
boolean platformOK = false;
if (platformsStr != null)
{
// Parse the list of platforms that native SMB is to be enabled for and
// check if the current platform is included
EnumSet enabledPlatforms = parsePlatformString(platformsStr);
if (enabledPlatforms.contains(getPlatformType()))
platformOK = true;
}
else
{
// No restriction on platforms
platformOK = true;
}
// Enable the TCP/IP SMB support, if enabled for this platform
setTcpipSMB(platformOK);
}
else
{
// Disable TCP/IP SMB support
setTcpipSMB(false);
}
// Check if Win32 NetBIOS is enabled
elem = config.getConfigElement("Win32NetBIOS");
if (elem != null)
{
// Check if the Win32 NetBIOS server name has been specified
String win32Name = elem.getAttribute("name");
if (win32Name != null && win32Name.length() > 0)
{
// Validate the name
if (win32Name.length() > 16)
throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS name, " + win32Name);
// Set the Win32 NetBIOS file server name
setWin32NetBIOSName(win32Name);
}
// Check if the Win32 NetBIOS LANA has been specified
String lanaStr = elem.getAttribute("lana");
if (lanaStr != null && lanaStr.length() > 0)
{
// Validate the LANA number
int lana = -1;
try
{
lana = Integer.parseInt(lanaStr);
}
catch (NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid win32 NetBIOS LANA specified");
}
// LANA should be in the range 0-255
if (lana < 0 || lana > 255)
throw new AlfrescoRuntimeException("Invalid Win32 NetBIOS LANA number, " + lana);
// Set the LANA number
setWin32LANA(lana);
}
// Check if the native NetBIOS interface has been specified, either 'winsock' or 'netbios'
String nativeAPI = elem.getAttribute("api");
if ( nativeAPI != null && nativeAPI.length() > 0)
{
// Validate the API type
boolean useWinsock = true;
if ( nativeAPI.equalsIgnoreCase("netbios"))
useWinsock = false;
else if ( nativeAPI.equalsIgnoreCase("winsock") == false)
throw new AlfrescoRuntimeException("Invalid NetBIOS API type, spefify 'winsock' or 'netbios'");
// Set the NetBIOS API to use
setWin32WinsockNetBIOS( useWinsock);
}
// Check if the current operating system is supported by the Win32
// NetBIOS handler
String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")
&& (osName.endsWith("95") == false && osName.endsWith("98") == false && osName.endsWith("ME") == false))
{
// Call the Win32NetBIOS native code to make sure it is initialized
if ( Win32NetBIOS.LanaEnumerate() != null)
{
// Enable Win32 NetBIOS
setWin32NetBIOS(true);
}
else
{
logger.warn("No NetBIOS LANAs available");
}
}
else
{
// Win32 NetBIOS not supported on the current operating system
setWin32NetBIOS(false);
}
}
else
{
// Disable Win32 NetBIOS
setWin32NetBIOS(false);
}
// Check if the host announcer should be enabled
elem = config.getConfigElement("Win32Announce");
if (elem != null)
{
// Check for an announcement interval
String interval = elem.getAttribute("interval");
if (interval != null && interval.length() > 0)
{
try
{
setWin32HostAnnounceInterval(Integer.parseInt(interval));
}
catch (NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid host announcement interval");
}
}
// Check if the domain name has been set, this is required if the
// host announcer is enabled
if (getDomainName() == null)
throw new AlfrescoRuntimeException("Domain name must be specified if host announcement is enabled");
// Enable Win32 NetBIOS host announcement
setWin32HostAnnouncer(true);
}
// Check if NetBIOS and/or TCP/IP SMB have been enabled
if (hasNetBIOSSMB() == false && hasTcpipSMB() == false && hasWin32NetBIOS() == false)
throw new AlfrescoRuntimeException("NetBIOS SMB, TCP/IP SMB or Win32 NetBIOS must be enabled");
// Check if WINS servers are configured
elem = config.getConfigElement("WINS");
if (elem != null)
{
// Get the primary WINS server
ConfigElement priWinsElem = elem.getChild("primary");
if (priWinsElem == null || priWinsElem.getValue().length() == 0)
throw new AlfrescoRuntimeException("No primary WINS server configured");
// Validate the WINS server address
InetAddress primaryWINS = null;
try
{
primaryWINS = InetAddress.getByName(priWinsElem.getValue());
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid primary WINS server address, " + priWinsElem.getValue());
}
// Check if a secondary WINS server has been specified
ConfigElement secWinsElem = elem.getChild("secondary");
InetAddress secondaryWINS = null;
if (secWinsElem != null)
{
// Validate the secondary WINS server address
try
{
secondaryWINS = InetAddress.getByName(secWinsElem.getValue());
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid secondary WINS server address, "
+ secWinsElem.getValue());
}
}
// Set the WINS server address(es)
setPrimaryWINSServer(primaryWINS);
if (secondaryWINS != null)
setSecondaryWINSServer(secondaryWINS);
// Pass the setting to the NetBIOS session class
NetBIOSSession.setWINSServer(primaryWINS);
}
// Check if WINS is configured, if we are running on Windows and socket based NetBIOS is enabled
else if (hasNetBIOSSMB() && getPlatformType() == PlatformType.WINDOWS)
{
// Get the WINS server list
String winsServers = Win32NetBIOS.getWINSServerList();
if (winsServers != null)
{
// Use the first WINS server address for now
StringTokenizer tokens = new StringTokenizer(winsServers, ",");
String addr = tokens.nextToken();
try
{
// Convert to a network address and check if the WINS server is accessible
InetAddress winsAddr = InetAddress.getByName(addr);
Socket winsSocket = new Socket();
InetSocketAddress sockAddr = new InetSocketAddress( winsAddr, RFCNetBIOSProtocol.NAME_PORT);
winsSocket.connect(sockAddr, 3000);
winsSocket.close();
// Set the primary WINS server address
setPrimaryWINSServer(winsAddr);
// Debug
if (logger.isDebugEnabled())
logger.debug("Configuring to use WINS server " + addr);
}
catch (UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Invalid auto WINS server address, " + addr);
}
catch (IOException ex)
{
if ( logger.isDebugEnabled())
logger.debug("Failed to connect to auto WINS server " + addr);
}
}
}
// Check if session debug is enabled
elem = config.getConfigElement("sessionDebug");
if (elem != null)
{
// Check for session debug flags
String flags = elem.getAttribute("flags");
int sessDbg = 0;
if (flags != null)
{
// Parse the flags
flags = flags.toUpperCase();
StringTokenizer token = new StringTokenizer(flags, ",");
while (token.hasMoreTokens())
{
// Get the current debug flag token
String dbg = token.nextToken().trim();
// Find the debug flag name
int idx = 0;
while (idx < m_sessDbgStr.length && m_sessDbgStr[idx].equalsIgnoreCase(dbg) == false)
idx++;
if (idx > m_sessDbgStr.length)
throw new AlfrescoRuntimeException("Invalid session debug flag, " + dbg);
// Set the debug flag
sessDbg += 1 << idx;
}
}
// Set the session debug flags
setSessionDebugFlags(sessDbg);
}
}
/**
* Process the FTP server configuration
*
* @param config Config
*/
private final void processFTPServerConfig(Config config)
{
// If the configuration section is not valid then FTP is disabled
if ( config == null || config.getConfigElements().isEmpty())
{
setFTPServerEnabled(false);
return;
}
// Check for a bind address
ConfigElement elem = config.getConfigElement("bindto");
if ( elem != null) {
// Validate the bind address
String bindText = elem.getValue();
try {
// Check the bind address
InetAddress bindAddr = InetAddress.getByName(bindText);
// Set the bind address for the FTP server
setFTPBindAddress(bindAddr);
}
catch (UnknownHostException ex) {
throw new AlfrescoRuntimeException("Invalid FTP bindto address, " + elem.getValue());
}
}
// Check for an FTP server port
elem = config.getConfigElement("port");
if ( elem != null) {
try {
setFTPPort(Integer.parseInt(elem.getValue()));
if ( getFTPPort() <= 0 || getFTPPort() >= 65535)
throw new AlfrescoRuntimeException("FTP server port out of valid range");
}
catch (NumberFormatException ex) {
throw new AlfrescoRuntimeException("Invalid FTP server port");
}
}
else {
// Use the default FTP port
setFTPPort(DefaultFTPServerPort);
}
// Check if anonymous login is allowed
elem = config.getConfigElement("allowAnonymous");
if ( elem != null) {
// Enable anonymous login to the FTP server
setAllowAnonymousFTP(true);
// Check if an anonymous account has been specified
String anonAcc = elem.getAttribute("user");
if ( anonAcc != null && anonAcc.length() > 0) {
// Set the anonymous account name
setAnonymousFTPAccount(anonAcc);
// Check if the anonymous account name is valid
if ( getAnonymousFTPAccount() == null || getAnonymousFTPAccount().length() == 0)
throw new AlfrescoRuntimeException("Anonymous FTP account invalid");
}
else {
// Use the default anonymous account name
setAnonymousFTPAccount(DefaultFTPAnonymousAccount);
}
}
else {
// Disable anonymous logins
setAllowAnonymousFTP(false);
}
// Check if a root path has been specified
elem = config.getConfigElement("rootDirectory");
if ( elem != null) {
// Get the root path
String rootPath = elem.getValue();
// Validate the root path
try {
// Parse the path
FTPPath ftpPath = new FTPPath(rootPath);
// Set the root path
setFTPRootPath(rootPath);
}
catch (InvalidPathException ex) {
throw new AlfrescoRuntimeException("Invalid FTP root directory, " + rootPath);
}
}
// Check if FTP debug is enabled
elem = config.getConfigElement("debug");
if (elem != null) {
// Check for FTP debug flags
String flags = elem.getAttribute("flags");
int ftpDbg = 0;
if ( flags != null) {
// Parse the flags
flags = flags.toUpperCase();
StringTokenizer token = new StringTokenizer(flags,",");
while ( token.hasMoreTokens()) {
// Get the current debug flag token
String dbg = token.nextToken().trim();
// Find the debug flag name
int idx = 0;
while ( idx < m_ftpDebugStr.length && m_ftpDebugStr[idx].equalsIgnoreCase(dbg) == false)
idx++;
if ( idx >= m_ftpDebugStr.length)
throw new AlfrescoRuntimeException("Invalid FTP debug flag, " + dbg);
// Set the debug flag
ftpDbg += 1 << idx;
}
}
// Set the FTP debug flags
setFTPDebug(ftpDbg);
}
}
/**
* Process the filesystems configuration
*
* @param config Config
*/
private final void processFilesystemsConfig(Config config)
{
// Check for the home folder filesystem
ConfigElement homeElem = config.getConfigElement("homeFolder");
if ( homeElem != null)
{
try
{
// Create the home folder share mapper
HomeShareMapper shareMapper = new HomeShareMapper();
shareMapper.initializeMapper( this, homeElem);
// Use the home folder share mapper
m_shareMapper = shareMapper;
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using home folder share mapper");
}
catch (InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException("Failed to initialize home folder share mapper", ex);
}
}
// Get the filesystem configuration elements
List filesysElems = config.getConfigElementList("filesystem");
if (filesysElems != null)
{
// Add the filesystems
for (int i = 0; i < filesysElems.size(); i++)
{
// Get the current filesystem configuration
ConfigElement elem = filesysElems.get(i);
String filesysName = elem.getAttribute("name");
try
{
// Create a new filesystem driver instance and create a context for
// the new filesystem
DiskInterface filesysDriver = this.diskInterface;
DiskDeviceContext filesysContext = (DiskDeviceContext) filesysDriver.createContext(elem);
// Check if an access control list has been specified
AccessControlList acls = null;
ConfigElement aclElem = elem.getChild("accessControl");
if (aclElem != null)
{
// Parse the access control list
acls = processAccessControlList(aclElem);
}
else if (hasGlobalAccessControls())
{
// Use the global access control list for this disk share
acls = getGlobalAccessControls();
}
// Check if change notifications are disabled
boolean changeNotify = elem.getChild("disableChangeNotification") == null ? true : false;
// Create the shared filesystem
DiskSharedDevice filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext);
// Add any access controls to the share
filesys.setAccessControlList(acls);
// Enable/disable change notification for this device
filesysContext.enableChangeHandler(changeNotify);
// Start the filesystem
filesysContext.startFilesystem(filesys);
// Create the shared device and add to the list of available
// shared filesystems
addShare(filesys);
}
catch (DeviceContextException ex)
{
throw new AlfrescoRuntimeException("Error creating filesystem " + filesysName, ex);
}
}
}
}
/**
* Process the security configuration
*
* @param config Config
*/
private final void processSecurityConfig(Config config)
{
// Check if global access controls have been specified
ConfigElement globalACLs = config.getConfigElement("globalAccessControl");
if (globalACLs != null)
{
// Parse the access control list
AccessControlList acls = processAccessControlList(globalACLs);
if (acls != null)
setGlobalAccessControls(acls);
}
// Check if a JCE provider class has been specified
ConfigElement jceElem = config.getConfigElement("JCEProvider");
if (jceElem != null)
{
// Set the JCE provider
setJCEProvider(jceElem.getValue());
}
else
{
// Use the default Cryptix JCE provider
setJCEProvider("cryptix.jce.provider.CryptixCrypto");
}
// Check if an authenticator has been specified
ConfigElement authElem = config.getConfigElement("authenticator");
if (authElem != null)
{
// Get the authenticator type, should be either 'local' or 'passthru'
String authType = authElem.getAttribute("type");
if (authType == null)
throw new AlfrescoRuntimeException("Authenticator type not specified");
// Set the authenticator class to use
SrvAuthenticator auth = null;
if (authType.equalsIgnoreCase("local"))
auth = new LocalAuthenticator();
else if (authType.equalsIgnoreCase("passthru"))
{
// Load the passthru authenticator dynamically
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.passthru.PassthruAuthenticator");
if ( auth == null)
throw new AlfrescoRuntimeException("Failed to load passthru authenticator");
}
else if (authType.equalsIgnoreCase("acegi"))
{
// Load the Acegi authenticator dynamically
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.passthru.AcegiPassthruAuthenticator");
if ( auth == null)
throw new AlfrescoRuntimeException("Failed to load Acegi passthru authenticator");
}
else if (authType.equalsIgnoreCase("alfresco"))
{
// Load the Alfresco authenticator dynamically
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.ntlm.AlfrescoAuthenticator");
if ( auth == null)
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.AlfrescoAuthenticator");
if ( auth == null)
throw new AlfrescoRuntimeException("Failed to load Alfresco authenticator");
}
else
throw new AlfrescoRuntimeException("Invalid authenticator type, " + authType);
// Get the allow guest setting
boolean allowGuest = authElem.getChild("allowGuest") != null ? true : false;
// Initialize and set the authenticator class
setAuthenticator(auth, authElem, allowGuest);
}
// Add the users
ConfigElement usersElem = config.getConfigElement("users");
if (usersElem != null)
{
// Get the list of user elements
List userElemList = usersElem.getChildren();
for (int i = 0; i < userElemList.size(); i++)
{
// Get the current user element
ConfigElement curUserElem = userElemList.get(i);
if (curUserElem.getName().equals("localuser"))
{
processUser(curUserElem);
}
}
}
}
/**
* Process an access control sub-section and return the access control list
*
* @param aclsElem ConfigElement
*/
private final AccessControlList processAccessControlList(ConfigElement aclsElem)
{
// Check if there is an access control manager configured
if (getAccessControlManager() == null)
throw new AlfrescoRuntimeException("No access control manager configured");
// Create the access control list
AccessControlList acls = new AccessControlList();
// Check if there is a default access level for the ACL group
String attrib = aclsElem.getAttribute("default");
if (attrib != null && attrib.length() > 0)
{
// Get the access level and validate
try
{
// Parse the access level name
int access = AccessControlParser.parseAccessTypeString(attrib);
// Set the default access level for the access control list
acls.setDefaultAccessLevel(access);
}
catch (InvalidACLTypeException ex)
{
throw new AlfrescoRuntimeException("Default access level error", ex);
}
catch (ACLParseException ex)
{
throw new AlfrescoRuntimeException("Default access level error", ex);
}
}
// Parse each access control element
List aclElemList = aclsElem.getChildren();
if (aclElemList != null && aclElemList.size() > 0)
{
// Create the access controls
for (int i = 0; i < aclsElem.getChildCount(); i++)
{
// Get the current ACL element
ConfigElement curAclElem = aclElemList.get(i);
try
{
// Create the access control and add to the list
acls.addControl(getAccessControlManager().createAccessControl(curAclElem.getName(), curAclElem));
}
catch (InvalidACLTypeException ex)
{
throw new AlfrescoRuntimeException("Invalid access control type - " + curAclElem.getName());
}
catch (ACLParseException ex)
{
throw new AlfrescoRuntimeException("Access control parse error (" + curAclElem.getName() + ")", ex);
}
}
}
// Check if there are no access control rules but the default access level is set to 'None',
// this is not allowed as the share would not be accessible or visible.
if (acls.getDefaultAccessLevel() == AccessControl.NoAccess && acls.numberOfControls() == 0)
throw new AlfrescoRuntimeException("Empty access control list and default access 'None' not allowed");
// Return the access control list
return acls;
}
/**
* Add a user account
*
* @param user ConfigElement
*/
private final void processUser(ConfigElement user)
{
// Get the username
String attr = user.getAttribute("name");
if (attr == null || attr.length() == 0)
throw new AlfrescoRuntimeException("User name not specified, or zero length");
// Check if the user already exists
String userName = attr;
if (hasUserAccounts() && getUserAccounts().findUser(userName) != null)
throw new AlfrescoRuntimeException("User " + userName + " already defined");
// Get the password for the account
ConfigElement elem = user.getChild("password");
if (elem == null)
throw new AlfrescoRuntimeException("No password specified for user " + userName);
String password = elem.getValue();
// Create the user account
UserAccount userAcc = new UserAccount(userName, password);
// Check if the user in an administrator
if (user.getChild("administrator") != null)
userAcc.setAdministrator(true);
// Get the real user name and comment
elem = user.getChild("realname");
if (elem != null)
userAcc.setRealName(elem.getValue());
elem = user.getChild("comment");
if (elem != null)
userAcc.setComment(elem.getValue());
// Add the user account
UserAccountList accList = getUserAccounts();
if (accList == null)
setUserAccounts(new UserAccountList());
getUserAccounts().addUser(userAcc);
}
/**
* Parse the platforms attribute returning the set of platform ids
*
* @param platformStr String
* @return EnumSet
*/
private final EnumSet parsePlatformString(String platformStr)
{
// Split the platform string and build up a set of platform types
EnumSet platformTypes = EnumSet.noneOf(PlatformType.class);
if (platformStr == null || platformStr.length() == 0)
return platformTypes;
StringTokenizer token = new StringTokenizer(platformStr.toUpperCase(), ",");
String typ = null;
try
{
while (token.hasMoreTokens())
{
// Get the current platform type string and validate
typ = token.nextToken().trim();
PlatformType platform = PlatformType.valueOf(typ);
if (platform != PlatformType.Unknown)
platformTypes.add(platform);
else
throw new AlfrescoRuntimeException("Invalid platform type, " + typ);
}
}
catch (IllegalArgumentException ex)
{
throw new AlfrescoRuntimeException("Invalid platform type, " + typ);
}
// Return the platform types
return platformTypes;
}
/**
* Add a shared device to the server configuration.
*
* @param shr SharedDevice
* @return boolean
*/
public final boolean addShare(SharedDevice shr)
{
return m_shareList.addShare(shr);
}
/**
* Add a server to the list of active servers
*
* @param srv NetworkServer
*/
public synchronized final void addServer(NetworkServer srv)
{
m_serverList.addServer(srv);
}
/**
* Find an active server using the protocol name
*
* @param proto String
* @return NetworkServer
*/
public final NetworkServer findServer(String proto)
{
return m_serverList.findServer(proto);
}
/**
* Remove an active server
*
* @param proto String
* @return NetworkServer
*/
public final NetworkServer removeServer(String proto)
{
return m_serverList.removeServer(proto);
}
/**
* Return the number of active servers
*
* @return int
*/
public final int numberOfServers()
{
return m_serverList.numberOfServers();
}
/**
* Return the server at the specified index
*
* @param idx int
* @return NetworkServer
*/
public final NetworkServer getServer(int idx)
{
return m_serverList.getServer(idx);
}
/**
* Check if there is an access control manager configured
*
* @return boolean
*/
public final boolean hasAccessControlManager()
{
return m_aclManager != null ? true : false;
}
/**
* Get the access control manager that is used to control per share access
*
* @return AccessControlManager
*/
public final AccessControlManager getAccessControlManager()
{
return m_aclManager;
}
/**
* Return the associated Acegi authentication manager
*
* @return AuthenticationManager
*/
public final AuthenticationManager getAuthenticationManager()
{
return acegiAuthMgr;
}
/**
* Check if the global access control list is configured
*
* @return boolean
*/
public final boolean hasGlobalAccessControls()
{
return m_globalACLs != null ? true : false;
}
/**
* Return the global access control list
*
* @return AccessControlList
*/
public final AccessControlList getGlobalAccessControls()
{
return m_globalACLs;
}
/**
* Get the authenticator object that is used to provide user and share connection
* authentication.
*
* @return Authenticator
*/
public final SrvAuthenticator getAuthenticator()
{
return m_authenticator;
}
/**
* Get the alfreso authentication service.
*
* @return
*/
public final AuthenticationService getAuthenticationService()
{
return authenticationService;
}
/**
* Return the authentication component, for access to internal functions
*
* @return AuthenticationComponent
*/
public final AuthenticationComponent getAuthenticationComponent()
{
return m_authComponent;
}
/**
* Return the node service
*
* @return NodeService
*/
public final NodeService getNodeService()
{
return m_nodeService;
}
/**
* Return the person service
*
* @return PersonService
*/
public final PersonService getPersonService()
{
return m_personService;
}
/**
* Return the transaction service
*
* @return TransactionService
*/
public final TransactionService getTransactionService()
{
return m_transactionService;
}
/**
* Return the local address that the SMB server should bind to.
*
* @return java.net.InetAddress
*/
public final InetAddress getSMBBindAddress()
{
return m_smbBindAddress;
}
/**
* Return the local address that the NetBIOS name server should bind to.
*
* @return java.net.InetAddress
*/
public final InetAddress getNetBIOSBindAddress()
{
return m_nbBindAddress;
}
/**
* Return the network broadcast mask to be used for broadcast datagrams.
*
* @return java.lang.String
*/
public final String getBroadcastMask()
{
return m_broadcast;
}
/**
* Return the server comment.
*
* @return java.lang.String
*/
public final String getComment()
{
return m_comment != null ? m_comment : "";
}
/**
* Return the disk interface to be used to create shares
*
* @return DiskInterface
*/
public final DiskInterface getDiskInterface()
{
return diskInterface;
}
/**
* Return the domain name.
*
* @return java.lang.String
*/
public final String getDomainName()
{
return m_domain;
}
/**
* Return the enabled SMB dialects that the server will use when negotiating sessions.
*
* @return DialectSelector
*/
public final DialectSelector getEnabledDialects()
{
return m_dialects;
}
/**
* Return the server name.
*
* @return java.lang.String
*/
public final String getServerName()
{
return m_name;
}
/**
* Return the server type flags.
*
* @return int
*/
public final int getServerType()
{
return m_srvType;
}
/**
* Return the server debug flags.
*
* @return int
*/
public final int getSessionDebugFlags()
{
return m_sessDebug;
}
/**
* Return the shared device list.
*
* @return SharedDeviceList
*/
public final SharedDeviceList getShares()
{
return m_shareList;
}
/**
* Return the share mapper
*
* @return ShareMapper
*/
public final ShareMapper getShareMapper()
{
return m_shareMapper;
}
/**
* Return the user account list.
*
* @return UserAccountList
*/
public final UserAccountList getUserAccounts()
{
return m_userList;
}
/**
* Return the Win32 NetBIOS server name, if null the default server name will be used
*
* @return String
*/
public final String getWin32ServerName()
{
return m_win32NBName;
}
/**
* Determine if the server should be announced via Win32 NetBIOS, so that it appears under
* Network Neighborhood.
*
* @return boolean
*/
public final boolean hasWin32EnableAnnouncer()
{
return m_win32NBAnnounce;
}
/**
* Return the Win32 NetBIOS host announcement interval, in minutes
*
* @return int
*/
public final int getWin32HostAnnounceInterval()
{
return m_win32NBAnnounceInterval;
}
/**
* Return the Win3 NetBIOS LANA number to use, or -1 for the first available
*
* @return int
*/
public final int getWin32LANA()
{
return m_win32NBLANA;
}
/**
* Determine if the Win32 Netbios() API or Winsock Netbios calls should be used
*
* @return boolean
*/
public final boolean useWinsockNetBIOS()
{
return m_win32NBUseWinsock;
}
/**
* Return the timezone name
*
* @return String
*/
public final String getTimeZone()
{
return m_timeZone;
}
/**
* Return the timezone offset from UTC in seconds
*
* @return int
*/
public final int getTimeZoneOffset()
{
return m_tzOffset;
}
/**
* Determine if the primary WINS server address has been set
*
* @return boolean
*/
public final boolean hasPrimaryWINSServer()
{
return m_winsPrimary != null ? true : false;
}
/**
* Return the primary WINS server address
*
* @return InetAddress
*/
public final InetAddress getPrimaryWINSServer()
{
return m_winsPrimary;
}
/**
* Determine if the secondary WINS server address has been set
*
* @return boolean
*/
public final boolean hasSecondaryWINSServer()
{
return m_winsSecondary != null ? true : false;
}
/**
* Return the secondary WINS server address
*
* @return InetAddress
*/
public final InetAddress getSecondaryWINSServer()
{
return m_winsSecondary;
}
/**
* Determine if the SMB server should bind to a particular local address
*
* @return boolean
*/
public final boolean hasSMBBindAddress()
{
return m_smbBindAddress != null ? true : false;
}
/**
* Determine if the NetBIOS name server should bind to a particular local address
*
* @return boolean
*/
public final boolean hasNetBIOSBindAddress()
{
return m_nbBindAddress != null ? true : false;
}
/**
* Determine if NetBIOS name server debugging is enabled
*
* @return boolean
*/
public final boolean hasNetBIOSDebug()
{
return m_nbDebug;
}
/**
* Determine if host announcement debugging is enabled
*
* @return boolean
*/
public final boolean hasHostAnnounceDebug()
{
return m_announceDebug;
}
/**
* Determine if the server should be announced so that it appears under Network Neighborhood.
*
* @return boolean
*/
public final boolean hasEnableAnnouncer()
{
return m_announce;
}
/**
* Return the host announcement interval, in minutes
*
* @return int
*/
public final int getHostAnnounceInterval()
{
return m_announceInterval;
}
/**
* Return the JCE provider class name
*
* @return String
*/
public final String getJCEProvider()
{
return m_jceProviderClass;
}
/**
* Get the local server name and optionally trim the domain name
*
* @param trimDomain boolean
* @return String
*/
public final String getLocalServerName(boolean trimDomain)
{
// Check if the name has already been set
if (m_localName != null)
return m_localName;
// Find the local server name
String srvName = null;
if (getPlatformType() == PlatformType.WINDOWS)
{
// Get the local name via JNI
srvName = Win32NetBIOS.GetLocalNetBIOSName();
}
else
{
// Get the DNS name of the local system
try
{
srvName = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException ex)
{
}
}
// Strip the domain name
if (trimDomain && srvName != null)
{
int pos = srvName.indexOf(".");
if (pos != -1)
srvName = srvName.substring(0, pos);
}
// Save the local server name
m_localName = srvName;
// Return the local server name
return srvName;
}
/**
* Get the local domain/workgroup name
*
* @return String
*/
public final String getLocalDomainName()
{
// Check if the local domain has been set
if (m_localDomain != null)
return m_localDomain;
// Find the local domain name
String domainName = null;
if (getPlatformType() == PlatformType.WINDOWS)
{
// Get the local domain/workgroup name via JNI
domainName = Win32NetBIOS.GetLocalDomainName();
// Debug
if (logger.isDebugEnabled())
logger.debug("Local domain name is " + domainName + " (via JNI)");
}
else
{
NetBIOSName nbName = null;
try
{
// Try and find the browse master on the local network
nbName = NetBIOSSession.FindName(NetBIOSName.BrowseMasterName, NetBIOSName.BrowseMasterGroup, 5000);
// Log the browse master details
if (logger.isDebugEnabled())
logger.debug("Found browse master at " + nbName.getIPAddressString(0));
// Get the NetBIOS name list from the browse master
NetBIOSNameList nbNameList = NetBIOSSession.FindNamesForAddress(nbName.getIPAddressString(0));
nbName = nbNameList.findName(NetBIOSName.MasterBrowser, false);
// Set the domain/workgroup name
if (nbName != null)
domainName = nbName.getName();
else
throw new AlfrescoRuntimeException("Failed to find local domain/workgroup name");
}
catch (IOException ex)
{
throw new AlfrescoRuntimeException("Failed to determine local domain/workgroup");
}
}
// Save the local domain name
m_localDomain = domainName;
// Return the local domain/workgroup name
return domainName;
}
/**
* Return the primary filesystem shared device, or null if not available
*
* @return DiskSharedDevice
*/
public final DiskSharedDevice getPrimaryFilesystem()
{
// Check if there are any global shares defined
SharedDeviceList shares = getShares();
DiskSharedDevice diskShare = null;
if ( shares != null && shares.numberOfShares() > 0)
{
// Find the first available filesystem device
Enumeration shareEnum = shares.enumerateShares();
while ( diskShare == null && shareEnum.hasMoreElements())
{
SharedDevice curShare = shareEnum.nextElement();
if ( curShare.getType() == ShareType.DISK)
diskShare = (DiskSharedDevice) curShare;
}
}
// Return the first filesystem device, or null
return diskShare;
}
/**
* Determine if Macintosh extension SMBs are enabled
*
* @return boolean
*/
public final boolean hasMacintoshExtensions()
{
return m_macExtensions;
}
/**
* Determine if there are any user accounts defined.
*
* @return boolean
*/
public final boolean hasUserAccounts()
{
if (m_userList != null && m_userList.numberOfUsers() > 0)
return true;
return false;
}
/**
* Determine if NetBIOS SMB is enabled
*
* @return boolean
*/
public final boolean hasNetBIOSSMB()
{
return m_netBIOSEnable;
}
/**
* Determine if TCP/IP SMB is enabled
*
* @return boolean
*/
public final boolean hasTcpipSMB()
{
return m_tcpSMBEnable;
}
/**
* Determine if Win32 NetBIOS is enabled
*
* @return boolean
*/
public final boolean hasWin32NetBIOS()
{
return m_win32NBEnable;
}
/**
* Check if the SMB server is enabled
*
* @return boolean
*/
public final boolean isSMBServerEnabled()
{
return m_smbEnable;
}
/**
* Set the SMB server enabled state
*
* @param ena boolean
*/
public final void setSMBServerEnabled(boolean ena)
{
m_smbEnable = ena;
}
/**
* Set the FTP server enabled state
*
* @param ena boolean
*/
public final void setFTPServerEnabled(boolean ena)
{
m_ftpEnable = ena;
}
/**
* Set the authenticator to be used to authenticate users and share connections.
*
* @param auth SrvAuthenticator
* @param params ConfigElement
* @param allowGuest boolean
*/
public final void setAuthenticator(SrvAuthenticator auth, ConfigElement params, boolean allowGuest)
{
// Set the server authenticator mode and guest access
auth.setAccessMode(SrvAuthenticator.USER_MODE);
auth.setAllowGuest(allowGuest);
// Initialize the authenticator using the parameter values
try
{
auth.initialize(this, params);
}
catch (InvalidConfigurationException ex)
{
throw new AlfrescoRuntimeException("Failed to initialize authenticator", ex);
}
// Set the server authenticator and initialization parameters
m_authenticator = auth;
}
/**
* Set the local address that the SMB server should bind to.
*
* @param addr InetAddress
*/
public final void setSMBBindAddress(InetAddress addr)
{
m_smbBindAddress = addr;
}
/**
* Set the local address that the NetBIOS name server should bind to.
*
* @param addr InetAddress
*/
public final void setNetBIOSBindAddress(InetAddress addr)
{
m_nbBindAddress = addr;
}
/**
* Set the broadcast mask to be used for broadcast datagrams.
*
* @param mask String
*/
public final void setBroadcastMask(String mask)
{
m_broadcast = mask;
// Copy settings to the NetBIOS session class
NetBIOSSession.setSubnetMask(mask);
}
/**
* Set the server comment.
*
* @param comment String
*/
public final void setComment(String comment)
{
m_comment = comment;
}
/**
* Set the domain that the server belongs to.
*
* @param domain String
*/
public final void setDomainName(String domain)
{
m_domain = domain;
}
/**
* Enable/disable the host announcer.
*
* @param b boolean
*/
public final void setHostAnnouncer(boolean b)
{
m_announce = b;
}
/**
* Set the host announcement interval, in minutes
*
* @param ival int
*/
public final void setHostAnnounceInterval(int ival)
{
m_announceInterval = ival;
}
/**
* Set the JCE provider
*
* @param providerClass String
*/
public final void setJCEProvider(String providerClass)
{
// Validate the JCE provider class
try
{
// Load the JCE provider class and validate
Object jceObj = Class.forName(providerClass).newInstance();
if (jceObj instanceof java.security.Provider)
{
// Inform listeners, validate the configuration change
Provider jceProvider = (Provider) jceObj;
// Save the JCE provider class name
m_jceProviderClass = providerClass;
// Add the JCE provider
Security.addProvider(jceProvider);
}
else
{
throw new AlfrescoRuntimeException("JCE provider class is not a valid Provider class");
}
}
catch (ClassNotFoundException ex)
{
throw new AlfrescoRuntimeException("JCE provider class " + providerClass + " not found");
}
catch (Exception ex)
{
throw new AlfrescoRuntimeException("JCE provider class error", ex);
}
}
/**
* Enable/disable NetBIOS name server debug output
*
* @param ena boolean
*/
public final void setNetBIOSDebug(boolean ena)
{
m_nbDebug = ena;
}
/**
* Enable/disable host announcement debug output
*
* @param ena boolean
*/
public final void setHostAnnounceDebug(boolean ena)
{
m_announceDebug = ena;
}
/**
* Set the server name.
*
* @param name String
*/
public final void setServerName(String name)
{
m_name = name;
}
/**
* Set the debug flags to be used by the server.
*
* @param flags int
*/
public final void setSessionDebugFlags(int flags)
{
m_sessDebug = flags;
}
/**
* Set the user account list.
*
* @param users UserAccountList
*/
public final void setUserAccounts(UserAccountList users)
{
m_userList = users;
}
/**
* Set the global access control list
*
* @param acls AccessControlList
*/
public final void setGlobalAccessControls(AccessControlList acls)
{
m_globalACLs = acls;
}
/**
* Enable/disable the NetBIOS SMB support
*
* @param ena boolean
*/
public final void setNetBIOSSMB(boolean ena)
{
m_netBIOSEnable = ena;
}
/**
* Enable/disable the TCP/IP SMB support
*
* @param ena boolean
*/
public final void setTcpipSMB(boolean ena)
{
m_tcpSMBEnable = ena;
}
/**
* Enable/disable the Win32 NetBIOS SMB support
*
* @param ena boolean
*/
public final void setWin32NetBIOS(boolean ena)
{
m_win32NBEnable = ena;
}
/**
* Set the Win32 NetBIOS file server name
*
* @param name String
*/
public final void setWin32NetBIOSName(String name)
{
m_win32NBName = name;
}
/**
* Enable/disable the Win32 NetBIOS host announcer.
*
* @param b boolean
*/
public final void setWin32HostAnnouncer(boolean b)
{
m_win32NBAnnounce = b;
}
/**
* Set the Win32 LANA to be used by the Win32 NetBIOS interface
*
* @param ival int
*/
public final void setWin32LANA(int ival)
{
m_win32NBLANA = ival;
}
/**
* Set the Win32 NetBIOS host announcement interval, in minutes
*
* @param ival int
*/
public final void setWin32HostAnnounceInterval(int ival)
{
m_win32NBAnnounceInterval = ival;
}
/**
* Set the Win32 NetBIOS interface to use either Winsock NetBIOS or the Netbios() API calls
*
* @param useWinsock boolean
*/
public final void setWin32WinsockNetBIOS(boolean useWinsock)
{
m_win32NBUseWinsock = useWinsock;
}
/**
* Set the server timezone name
*
* @param name String
* @exception InvalidConfigurationException If the timezone is invalid
*/
public final void setTimeZone(String name) throws InvalidConfigurationException
{
// Validate the timezone
TimeZone tz = TimeZone.getTimeZone(name);
if (tz == null)
throw new InvalidConfigurationException("Invalid timezone, " + name);
// Set the timezone name and offset from UTC in minutes
//
// Invert the result of TimeZone.getRawOffset() as SMB/CIFS requires
// positive minutes west of UTC
m_timeZone = name;
m_tzOffset = -(tz.getRawOffset() / 60000);
}
/**
* Set the timezone offset from UTC in seconds (+/-)
*
* @param offset int
*/
public final void setTimeZoneOffset(int offset)
{
m_tzOffset = offset;
}
/**
* Set the primary WINS server address
*
* @param addr InetAddress
*/
public final void setPrimaryWINSServer(InetAddress addr)
{
m_winsPrimary = addr;
}
/**
* Set the secondary WINS server address
*
* @param addr InetAddress
*/
public final void setSecondaryWINSServer(InetAddress addr)
{
m_winsSecondary = addr;
}
/**
* Check if the FTP server is enabled
*
* @return boolean
*/
public final boolean isFTPServerEnabled()
{
return m_ftpEnable;
}
/**
* Return the FTP server bind address, may be null to indicate bind to all available addresses
*
* @return InetAddress
*/
public final InetAddress getFTPBindAddress()
{
return m_ftpBindAddress;
}
/**
* Return the FTP server port to use for incoming connections
*
* @return int
*/
public final int getFTPPort()
{
return m_ftpPort;
}
/**
* Determine if anonymous FTP access is allowed
*
* @return boolean
*/
public final boolean allowAnonymousFTP()
{
return m_ftpAllowAnonymous;
}
/**
* Return the anonymous FTP account name
*
* @return String
*/
public final String getAnonymousFTPAccount()
{
return m_ftpAnonymousAccount;
}
/**
* Return the FTP debug flags
*
* @return int
*/
public final int getFTPDebug()
{
return m_ftpDebug;
}
/**
* Check if an FTP root path has been configured
*
* @return boolean
*/
public final boolean hasFTPRootPath()
{
return m_ftpRootPath != null ? true : false;
}
/**
* Return the FTP root path
*
* @return String
*/
public final String getFTPRootPath()
{
return m_ftpRootPath;
}
/**
* Set the FTP server bind address, may be null to indicate bind to all available addresses
*
* @param addr InetAddress
*/
public final void setFTPBindAddress(InetAddress addr)
{
m_ftpBindAddress = addr;
}
/**
* Set the FTP server port to use for incoming connections, -1 indicates disable the FTP server
*
* @param port int
*/
public final void setFTPPort(int port)
{
m_ftpPort = port;
}
/**
* Set the FTP root path
*
* @param path String
*/
public final void setFTPRootPath(String path)
{
m_ftpRootPath = path;
}
/**
* Enable/disable anonymous FTP access
*
* @param ena boolean
*/
public final void setAllowAnonymousFTP(boolean ena)
{
m_ftpAllowAnonymous = ena;
}
/**
* Set the anonymous FTP account name
*
* @param acc String
*/
public final void setAnonymousFTPAccount(String acc)
{
m_ftpAnonymousAccount = acc;
}
/**
* Set the FTP debug flags
*
* @param dbg int
*/
public final void setFTPDebug(int dbg)
{
m_ftpDebug = dbg;
}
/**
* Close the server configuration, used to close various components that are shared between protocol
* handlers.
*/
public final void closeConfiguration()
{
// Close the authenticator
if ( getAuthenticator() != null)
{
getAuthenticator().closeAuthenticator();
m_authenticator = null;
}
// Close the shared filesystems
if ( getShares() != null && getShares().numberOfShares() > 0)
{
// Close the shared filesystems
Enumeration shareEnum = getShares().enumerateShares();
while ( shareEnum.hasMoreElements())
{
SharedDevice share = shareEnum.nextElement();
DeviceContext devCtx = share.getContext();
if ( devCtx != null)
devCtx.CloseContext();
}
}
}
/**
* Load an authenticator using dyanmic loading
*
* @param className String
* @return SrvAuthenticator
*/
private final SrvAuthenticator loadAuthenticatorClass(String className)
{
SrvAuthenticator srvAuth = null;
try
{
// Load the authenticator class
Object authObj = Class.forName(className).newInstance();
// Verify that the class is an authenticator
if ( authObj instanceof SrvAuthenticator)
srvAuth = (SrvAuthenticator) authObj;
}
catch (Exception ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Failed to load authenticator class " + className);
}
// Return the authenticator class, or null if not available or invalid
return srvAuth;
}
}