org.alfresco.filesys.auth.PassthruServerFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.filesys.auth.PassthruServerFactory.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.filesys.auth;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.StringTokenizer;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.jlan.netbios.NetBIOSSession;
import org.alfresco.jlan.server.auth.passthru.AuthSessionFactory;
import org.alfresco.jlan.server.auth.passthru.PassthruServers;
import org.alfresco.jlan.server.config.InvalidConfigurationException;
import org.alfresco.jlan.smb.Protocol;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * A Factory for {@link PassthruServers} objects, allowing setting of the server list via local server, individual
 * servers or domain name.
 * 
 * @author dward
 */
public class PassthruServerFactory implements FactoryBean, InitializingBean, DisposableBean {
    private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.auth");

    public final static int DefaultSessionTmo = 5000; // 5 seconds
    public final static int MinSessionTmo = 2000; // 2 seconds
    public final static int MaxSessionTmo = 30000; // 30 seconds

    public final static int MinCheckInterval = 10; // 10 seconds
    public final static int MaxCheckInterval = 15 * 60; // 15 minutes

    private Integer timeout;

    private boolean localServer;

    private String server;

    private String domain;

    private Integer offlineCheckInterval;

    private PassthruServers passthruServers;

    private boolean nullDomainUseAnyServer;

    /**
     * Sets the timeout for opening a session to an authentication server
     * 
     * @param timeout
     *            a time period in milliseconds
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * Indicates whether the local server should be used as the authentication server
     * 
     * @param localServer
     *            <code>true</code> if the local server should be used as the authentication server
     */
    public void setLocalServer(boolean localServer) {
        this.localServer = localServer;
    }

    /**
     * Sets the server(s) to authenticate against.
     * 
     * @param server
     *            comma-delimited list of server names
     */
    public void setServer(String server) {
        this.server = server;
    }

    /**
     * Sets the domain to authenticate against
     * 
     * @param domain
     *            a domain name
     */
    public void setDomain(String domain) {
        this.domain = domain;
    }

    /**
     * Sets the offline server check interval in seconds
     * 
     * @param offlineCheckInterval
     *            a time interval in seconds
     */
    public void setOfflineCheckInterval(Integer offlineCheckInterval) {
        this.offlineCheckInterval = offlineCheckInterval;
    }

    /**
     * Set the null domain to use any available server option
     * 
     * @param nullDomain boolean
     */
    public final void setNullDomainUseAnyServer(boolean nullDomain) {
        this.nullDomainUseAnyServer = nullDomain;
    }

    /**
     * Set the protocol order for passthru connections
     * 
     * @param protoOrder
     *            a comma-delimited list containing one or more of "NetBIOS" and "TCPIP" in any order
     */
    public void setProtocolOrder(String protoOrder) {
        // Parse the protocol order list

        StringTokenizer tokens = new StringTokenizer(protoOrder, ",");
        int primaryProto = Protocol.None;
        int secondaryProto = Protocol.None;

        // There should only be one or two tokens

        if (tokens.countTokens() > 2)
            throw new AlfrescoRuntimeException("Invalid protocol order list, " + protoOrder);

        // Get the primary protocol

        if (tokens.hasMoreTokens()) {
            // Parse the primary protocol

            String primaryStr = tokens.nextToken();

            if (primaryStr.equalsIgnoreCase("TCPIP"))
                primaryProto = Protocol.NativeSMB;
            else if (primaryStr.equalsIgnoreCase("NetBIOS"))
                primaryProto = Protocol.TCPNetBIOS;
            else
                throw new AlfrescoRuntimeException("Invalid protocol type, " + primaryStr);

            // Check if there is a secondary protocol, and validate

            if (tokens.hasMoreTokens()) {
                // Parse the secondary protocol

                String secondaryStr = tokens.nextToken();

                if (secondaryStr.equalsIgnoreCase("TCPIP") && primaryProto != Protocol.NativeSMB)
                    secondaryProto = Protocol.NativeSMB;
                else if (secondaryStr.equalsIgnoreCase("NetBIOS") && primaryProto != Protocol.TCPNetBIOS)
                    secondaryProto = Protocol.TCPNetBIOS;
                else
                    throw new AlfrescoRuntimeException("Invalid secondary protocol, " + secondaryStr);
            }
        }

        // Set the protocol order used for passthru authentication sessions

        AuthSessionFactory.setProtocolOrder(primaryProto, secondaryProto);

        // DEBUG

        if (logger.isDebugEnabled())
            logger.debug("Protocol order primary=" + Protocol.asString(primaryProto) + ", secondary="
                    + Protocol.asString(secondaryProto));
    }

    /**
     * Set the broadcast mask to use for NetBIOS name lookups
     * 
     * @param bcastMask String
     * @exception AlfrescoRuntimeException
     */
    public final void setBroadcastMask(String bcastMask) throws IOException {

        if (bcastMask == null || bcastMask.length() == 0) {

            // Clear the NetBIOS subnet mask

            NetBIOSSession.setDefaultSubnetMask(null);
            return;
        }

        // Find the network adapter with the matching broadcast mask

        try {
            Enumeration<NetworkInterface> netEnum = NetworkInterface.getNetworkInterfaces();
            NetworkInterface bcastIface = null;

            while (netEnum.hasMoreElements() && bcastIface == null) {

                NetworkInterface ni = netEnum.nextElement();
                for (InterfaceAddress iAddr : ni.getInterfaceAddresses()) {
                    InetAddress broadcast = iAddr.getBroadcast();
                    if (broadcast != null && broadcast.getHostAddress().equals(bcastMask))
                        bcastIface = ni;
                }
            }

            // DEBUG

            if (logger.isDebugEnabled()) {
                if (bcastIface != null)
                    logger.debug("Broadcast mask " + bcastMask + " found on network interface "
                            + bcastIface.getDisplayName() + "/" + bcastIface.getName());
                else
                    logger.debug("Failed to find network interface for broadcast mask " + bcastMask);
            }

            // Check if we found a valid network interface for the broadcast mask

            if (bcastIface == null)
                throw new AlfrescoRuntimeException(
                        "Network interface for broadcast mask " + bcastMask + " not found");

            // Set the NetBIOS broadcast mask

            NetBIOSSession.setDefaultSubnetMask(bcastMask);
        } catch (SocketException ex) {
        }
    }

    public void afterPropertiesSet() throws InvalidConfigurationException {
        // Check if the offline check interval has been specified
        if (this.offlineCheckInterval != null) {
            // Range check the value

            if (this.offlineCheckInterval < MinCheckInterval || this.offlineCheckInterval > MaxCheckInterval)
                throw new InvalidConfigurationException("Invalid offline check interval, valid range is "
                        + MinCheckInterval + " to " + MaxCheckInterval);

            // Set the offline check interval for offline passthru servers

            passthruServers = new PassthruServers(this.offlineCheckInterval);

            // DEBUG

            if (logger.isDebugEnabled())
                logger.debug("Using offline check interval of " + this.offlineCheckInterval + " seconds");
        } else {
            // Create the passthru server list with the default offline check interval

            passthruServers = new PassthruServers();
        }

        // Propagate the debug setting

        if (logger.isDebugEnabled())
            passthruServers.setDebug(true);

        // Check if the session timeout has been specified

        if (this.timeout != null) {

            // Range check the timeout

            if (this.timeout < MinSessionTmo || this.timeout > MaxSessionTmo)
                throw new InvalidConfigurationException(
                        "Invalid session timeout, valid range is " + MinSessionTmo + " to " + MaxSessionTmo);

            // Set the session timeout for connecting to an authentication server

            passthruServers.setConnectionTimeout(this.timeout);
        }

        passthruServers.setNullDomainUseAnyServer(this.nullDomainUseAnyServer);

        // Check if a server name has been specified

        String srvList = null;
        if (localServer) {
            try {
                // Get the list of local network addresses

                InetAddress[] localAddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());

                // Build the list of local addresses

                if (localAddrs != null && localAddrs.length > 0) {
                    StringBuilder addrStr = new StringBuilder();

                    for (InetAddress curAddr : localAddrs) {
                        if (curAddr.isLoopbackAddress() == false) {
                            addrStr.append(curAddr.getHostAddress());
                            addrStr.append(",");
                        }
                    }

                    if (addrStr.length() > 0)
                        addrStr.setLength(addrStr.length() - 1);

                    // Set the server list using the local address list

                    srvList = addrStr.toString();
                } else
                    throw new AlfrescoRuntimeException("No local server address(es)");
            } catch (UnknownHostException ex) {
                throw new AlfrescoRuntimeException("Failed to get local address list");
            }
        }

        if (this.server != null && this.server.length() > 0) {

            // Check if the server name was already set

            if (srvList != null)
                throw new AlfrescoRuntimeException("Set passthru server via local server or specify name");

            // Get the passthru authenticator server name

            srvList = this.server;
        }

        // If the passthru server name has been set initialize the passthru connection

        if (srvList != null) {
            // Initialize using a list of server names/addresses

            passthruServers.setServerList(srvList);
        } else {

            // Get the domain/workgroup name

            String domainName = null;

            // Check if a domain name has been specified

            if (this.domain != null && this.domain.length() > 0) {

                // Check if the authentication server has already been set, ie. server name was also specified

                if (srvList != null)
                    throw new AlfrescoRuntimeException("Specify server or domain name for passthru authentication");

                domainName = this.domain;
            }

            // If the domain name has been set initialize the passthru connection

            if (domainName != null) {
                try {
                    // Initialize using the domain

                    passthruServers.setDomain(domainName);
                } catch (IOException ex) {
                    throw new AlfrescoRuntimeException("Error setting passthru domain, " + ex.getMessage());
                }
            }
        }

        // Check if we have an authentication server

        if (passthruServers.getTotalServerCount() == 0)
            throw new AlfrescoRuntimeException("No valid authentication servers found for passthru");
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.beans.factory.InitializingBean#getObject()
     */
    public Object getObject() {
        return passthruServers;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.beans.factory.FactoryBean#getObjectType()
     */
    public Class<?> getObjectType() {
        return PassthruServers.class;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.beans.factory.FactoryBean#isSingleton()
     */
    public boolean isSingleton() {
        return true;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.beans.factory.DisposableBean#destroy()
     */
    public void destroy() throws Exception {
        passthruServers.shutdown();
    }
}