Gary Spencer 3f6cff061e Added checks to the NetBIOS name server config/startup to make sure the server has at least one valid local IP address.
Linux often defaults the local host name to the 127.0.0.1 address which causes problems with name lookups.
(Fixes AR-422)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2361 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2006-02-13 18:11:33 +00:00

3050 lines
86 KiB
Java

/*
* 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.ConfigService;
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;
/**
* <p>
* 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 authenticationManager;
// Configuration service
private ConfigService configService;
/** 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_authenticationComponent;
// Various services
private NodeService m_nodeService;
private PersonService m_personService;
private TransactionService m_transactionService;
/**
* Class constructor
*/
public ServerConfiguration()
{
// 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();
}
public void setAuthenticationManager(AuthenticationManager authenticationManager)
{
this.authenticationManager = authenticationManager;
}
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
public void setDiskInterface(DiskInterface diskInterface)
{
this.diskInterface = diskInterface;
}
public void setAuthenticationComponent(AuthenticationComponent component)
{
m_authenticationComponent = component;
}
public void setNodeService(NodeService service)
{
m_nodeService = service;
}
public void setPersonService(PersonService service)
{
m_personService = service;
}
public void setTransactionService(TransactionService service)
{
m_transactionService = service;
}
/**
* @return Returns true if the configuration was fully initialised
*/
public boolean isInitialised()
{
return initialised;
}
/**
* Initialize the configuration using the configuration service
*/
public void init()
{
// check that all required properties have been set
if (authenticationManager == null)
{
throw new AlfrescoRuntimeException("Property 'authenticationManager' not set");
}
else if (m_authenticationComponent == null)
{
throw new AlfrescoRuntimeException("Property 'authenticationComponent' not set");
}
else if (authenticationService == null)
{
throw new AlfrescoRuntimeException("Property 'authenticationService' not set");
}
else if (m_nodeService == null)
{
throw new AlfrescoRuntimeException("Property 'nodeService' not set");
}
else if (m_personService == null)
{
throw new AlfrescoRuntimeException("Property 'personService' not set");
}
else if (m_transactionService == null)
{
throw new AlfrescoRuntimeException("Property 'transactionService' not set");
}
else if (diskInterface == null)
{
throw new AlfrescoRuntimeException("Property 'diskInterface' not set");
}
else if (configService == null)
{
throw new AlfrescoRuntimeException("Property 'configService' not set");
}
initialised = false;
// Create the configuration context
ConfigLookupContext configCtx = new ConfigLookupContext(ConfigArea);
// Set the platform type
determinePlatformType();
try
{
// Process the CIFS server configuration
Config config = configService.getConfig(ConfigCIFS, configCtx);
processCIFSServerConfig(config);
// Process the FTP server configuration
config = configService.getConfig(ConfigFTP, configCtx);
processFTPServerConfig(config);
// Process the security configuration
config = configService.getConfig(ConfigSecurity, configCtx);
processSecurityConfig(config);
// Process the filesystems configuration
config = configService.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
String localDomain = getLocalDomainName();
if ( localDomain == null && getPlatformType() != PlatformType.WINDOWS)
{
// Use a default domain/workgroup name
localDomain = "WORKGROUP";
// Output a warning
logger.error("Failed to get local domain/workgroup name, using default of " + localDomain);
logger.error("(This may be due to firewall settings or incorrect <broadcast> setting)");
}
// Set the local domain/workgroup that the CIFS server belongs to
setDomainName( localDomain);
}
// 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<PlatformType> 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
{
// Get a list of all the local addresses
InetAddress[] addrs = null;
try
{
// Get the local server IP address list
addrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
}
catch (UnknownHostException ex)
{
logger.error("Failed to get local address list", ex);
}
// Check the address list for one or more valid local addresses filtering out the loopback address
int addrCnt = 0;
if ( addrs != null)
{
for (int i = 0; i < addrs.length; i++)
{
// Check for a valid address, filter out '127.0.0.1' and '0.0.0.0' addresses
if (addrs[i].getHostAddress().equals("127.0.0.1") == false
&& addrs[i].getHostAddress().equals("0.0.0.0") == false)
addrCnt++;
}
}
// Check if any addresses were found
if ( addrCnt == 0)
{
// Log the available IP addresses
if ( logger.isDebugEnabled())
{
logger.debug("Local address list dump :-");
if ( addrs != null)
{
for ( int i = 0; i < addrs.length; i++)
logger.debug( " Address: " + addrs[i]);
}
else
logger.debug(" No addresses");
}
// Throw an exception to stop the CIFS/NetBIOS name server from starting
throw new AlfrescoRuntimeException( "Failed to get IP address(es) for the local server, check hosts file and/or DNS setup");
}
}
}
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<PlatformType> 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)
{
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<ConfigElement> 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 and map unknown user to guest settings
boolean allowGuest = authElem.getChild("allowGuest") != null ? true : false;
boolean mapGuest = authElem.getChild("mapUnknownUserToGuest") != null ? true : false;
// Initialize and set the authenticator class
setAuthenticator(auth, authElem, allowGuest);
auth.setMapToGuest( mapGuest);
}
// Add the users
ConfigElement usersElem = config.getConfigElement("users");
if (usersElem != null)
{
// Get the list of user elements
List<ConfigElement> 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<ConfigElement> 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<PlatformType>
*/
private final EnumSet<PlatformType> parsePlatformString(String platformStr)
{
// Split the platform string and build up a set of platform types
EnumSet<PlatformType> 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 authenticationManager;
}
/**
* 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_authenticationComponent;
}
/**
* 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();
}
catch (IOException ex)
{
}
}
// 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<SharedDevice> 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<SharedDevice> 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;
}
}