mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged V2.0 to HEAD
5450: (from V1.4) 5423 (V1.4): CIFS authentication 5451: (from V1.4) 5432 (V1.4): 'No root node' fix 5437 (V1.4): EHCache upgrade 5440 (V1.4): AR-1355 - Ticket cache config fix 5442 (V1.4): Bootstrap reorganization 5446 (V1.4): AR-1353 5452: (from V1.4) 5391: AR-1310 (script rename fix) 5453: Win32NetBIOS LANA 5454: CIFS unused code git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5483 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -247,6 +247,15 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Perform index recovery before applying any patches -->
|
||||||
|
<!-- rebuild the index if required - before we check that it is there -->
|
||||||
|
|
||||||
|
<bean id="indexRecoveryBootstrap" class="org.alfresco.repo.node.index.IndexRecoveryBootstrapBean" >
|
||||||
|
<property name="indexRecoveryComponent">
|
||||||
|
<ref bean="indexRecoveryComponent"/>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- This component checks the interconnection between the metadata, indexes and content -->
|
<!-- This component checks the interconnection between the metadata, indexes and content -->
|
||||||
<bean id="configurationChecker" class="org.alfresco.repo.admin.ConfigurationChecker">
|
<bean id="configurationChecker" class="org.alfresco.repo.admin.ConfigurationChecker">
|
||||||
<property name="strict">
|
<property name="strict">
|
||||||
@@ -328,6 +337,14 @@
|
|||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Start the quartz scheduler -->
|
||||||
|
|
||||||
|
<bean id="schedulerStarter" class="org.alfresco.util.SchedulerStarterBean" >
|
||||||
|
<property name="scheduler">
|
||||||
|
<ref bean="schedulerFactory"/>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Startup Message -->
|
<!-- Startup Message -->
|
||||||
|
|
||||||
<bean id="startupLog" class="org.alfresco.repo.descriptor.DescriptorStartupLog">
|
<bean id="startupLog" class="org.alfresco.repo.descriptor.DescriptorStartupLog">
|
||||||
|
@@ -260,7 +260,7 @@
|
|||||||
name="org.alfresco.cache.ticketsCache"
|
name="org.alfresco.cache.ticketsCache"
|
||||||
maxElementsInMemory="1000"
|
maxElementsInMemory="1000"
|
||||||
eternal="true"
|
eternal="true"
|
||||||
overflowToDisk="false"
|
overflowToDisk="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</ehcache>
|
</ehcache>
|
@@ -26,7 +26,7 @@
|
|||||||
<!--
|
<!--
|
||||||
<cacheManagerPeerListenerFactory
|
<cacheManagerPeerListenerFactory
|
||||||
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
|
||||||
properties="port=40001, socketTimeoutMillis=2000"/>
|
properties="port=40001, socketTimeoutMillis=5000"/>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- ================================================================= -->
|
<!-- ================================================================= -->
|
||||||
@@ -489,7 +489,7 @@
|
|||||||
name="org.alfresco.cache.ticketsCache"
|
name="org.alfresco.cache.ticketsCache"
|
||||||
maxElementsInMemory="1000"
|
maxElementsInMemory="1000"
|
||||||
eternal="true"
|
eternal="true"
|
||||||
overflowToDisk="false">
|
overflowToDisk="true">
|
||||||
|
|
||||||
<cacheEventListenerFactory
|
<cacheEventListenerFactory
|
||||||
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
@@ -16,6 +16,10 @@
|
|||||||
<property name="schedulerName">
|
<property name="schedulerName">
|
||||||
<value>DefaultScheduler</value>
|
<value>DefaultScheduler</value>
|
||||||
</property>
|
</property>
|
||||||
|
<!-- Do not auto start the scheduler - this is done at the end of the bootstrap process -->
|
||||||
|
<property name="autoStartup">
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -48,6 +52,8 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- This has now been moved into the bootstrap process and is not required here -->
|
||||||
|
<!--
|
||||||
<bean id="indexRecoveryTrigger" class="org.alfresco.util.TriggerBean">
|
<bean id="indexRecoveryTrigger" class="org.alfresco.util.TriggerBean">
|
||||||
<property name="jobDetail">
|
<property name="jobDetail">
|
||||||
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
|
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||||
@@ -73,6 +79,7 @@
|
|||||||
<value>0</value>
|
<value>0</value>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
-->
|
||||||
|
|
||||||
<bean id="tempFileCleanerTrigger" class="org.alfresco.util.TriggerBean">
|
<bean id="tempFileCleanerTrigger" class="org.alfresco.util.TriggerBean">
|
||||||
<property name="jobDetail">
|
<property name="jobDetail">
|
||||||
|
@@ -529,7 +529,7 @@ public class Win32NetBIOS
|
|||||||
String ipAddr = niEnum.nextElement();
|
String ipAddr = niEnum.nextElement();
|
||||||
NetworkInterface ni = niList.get(ipAddr);
|
NetworkInterface ni = niList.get(ipAddr);
|
||||||
|
|
||||||
if (ni.getDisplayName().equalsIgnoreCase(name))
|
if (ni.getName().equalsIgnoreCase(name))
|
||||||
{
|
{
|
||||||
|
|
||||||
// Return the LANA for the network adapters TCP/IP address
|
// Return the LANA for the network adapters TCP/IP address
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
package org.alfresco.filesys.server.auth;
|
package org.alfresco.filesys.server.auth;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
|
||||||
import org.alfresco.filesys.server.SrvSession;
|
import org.alfresco.filesys.server.SrvSession;
|
||||||
@@ -32,6 +33,7 @@ import org.alfresco.filesys.server.auth.AuthContext;
|
|||||||
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
||||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||||
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
||||||
|
import org.alfresco.filesys.server.core.SharedDevice;
|
||||||
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
||||||
import org.alfresco.filesys.util.HexDump;
|
import org.alfresco.filesys.util.HexDump;
|
||||||
import org.alfresco.repo.security.authentication.NTLMMode;
|
import org.alfresco.repo.security.authentication.NTLMMode;
|
||||||
@@ -190,6 +192,25 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
|||||||
return authSts;
|
return authSts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate a connection to a share.
|
||||||
|
*
|
||||||
|
* @param client User/client details from the tree connect request.
|
||||||
|
* @param share Shared device the client wants to connect to.
|
||||||
|
* @param pwd Share password.
|
||||||
|
* @param sess Server session.
|
||||||
|
* @return int Granted file permission level or disallow status if negative. See the
|
||||||
|
* FilePermission class.
|
||||||
|
*/
|
||||||
|
public int authenticateShareConnect(ClientInfo client, SharedDevice share, String sharePwd, SrvSession sess)
|
||||||
|
{
|
||||||
|
// Allow write access
|
||||||
|
//
|
||||||
|
// Main authentication is handled by authenticateUser()
|
||||||
|
|
||||||
|
return CifsAuthenticator.Writeable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an authentication context for the new session
|
* Return an authentication context for the new session
|
||||||
*
|
*
|
||||||
@@ -278,7 +299,9 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
|||||||
// Generate the local encrypted password using the challenge that was sent to the client
|
// Generate the local encrypted password using the challenge that was sent to the client
|
||||||
|
|
||||||
byte[] p21 = new byte[21];
|
byte[] p21 = new byte[21];
|
||||||
byte[] md4byts = m_md4Encoder.decodeHash(md4hash);
|
byte[] md4byts = null;
|
||||||
|
|
||||||
|
md4byts = m_md4Encoder.decodeHash(md4hash);
|
||||||
System.arraycopy(md4byts, 0, p21, 0, 16);
|
System.arraycopy(md4byts, 0, p21, 0, 16);
|
||||||
|
|
||||||
// Get the challenge that was sent to the client
|
// Get the challenge that was sent to the client
|
||||||
@@ -321,6 +344,11 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
|||||||
return CifsAuthenticator.AUTH_BADPASSWORD;
|
return CifsAuthenticator.AUTH_BADPASSWORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
|
||||||
|
if ( logger.isInfoEnabled())
|
||||||
|
logger.info( "Logged on user " + client.getUserName() + " (" + sess.getRemoteAddress() + ") using auto-logon shared password");
|
||||||
|
|
||||||
// Set the current user to be authenticated, save the authentication token
|
// Set the current user to be authenticated, save the authentication token
|
||||||
|
|
||||||
client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName()));
|
client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName()));
|
||||||
@@ -368,6 +396,10 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
|||||||
|
|
||||||
sess.beginReadTransaction( m_transactionService);
|
sess.beginReadTransaction( m_transactionService);
|
||||||
|
|
||||||
|
// Default logon status to disallow
|
||||||
|
|
||||||
|
int authSts = CifsAuthenticator.AUTH_DISALLOW;
|
||||||
|
|
||||||
// Get the authentication token for the session
|
// Get the authentication token for the session
|
||||||
|
|
||||||
NTLMPassthruToken authToken = (NTLMPassthruToken) sess.getAuthenticationToken();
|
NTLMPassthruToken authToken = (NTLMPassthruToken) sess.getAuthenticationToken();
|
||||||
@@ -377,7 +409,6 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
|||||||
|
|
||||||
// Get the appropriate hashed password for the algorithm
|
// Get the appropriate hashed password for the algorithm
|
||||||
|
|
||||||
int authSts = CifsAuthenticator.AUTH_DISALLOW;
|
|
||||||
byte[] hashedPassword = null;
|
byte[] hashedPassword = null;
|
||||||
|
|
||||||
if ( alg == NTLM1)
|
if ( alg == NTLM1)
|
||||||
|
@@ -495,7 +495,7 @@ public abstract class CifsAuthenticator
|
|||||||
|
|
||||||
// Check if this is a null session logon
|
// Check if this is a null session logon
|
||||||
|
|
||||||
if (user.length() == 0 && domain.length() == 0 && uniPwdLen == 0 && ascPwdLen == 1)
|
if (user.length() == 0 && uniPwdLen == 0 && ascPwdLen <= 1)
|
||||||
client.setLogonType(ClientInfo.LogonNull);
|
client.setLogonType(ClientInfo.LogonNull);
|
||||||
|
|
||||||
// Authenticate the user
|
// Authenticate the user
|
||||||
|
@@ -136,10 +136,11 @@ public final class AuthSessionFactory
|
|||||||
* @param pkt SMBPacket to build the negotiate request
|
* @param pkt SMBPacket to build the negotiate request
|
||||||
* @param dlct SMB dialects to negotiate
|
* @param dlct SMB dialects to negotiate
|
||||||
* @param pid Process id to be used by this new session
|
* @param pid Process id to be used by this new session
|
||||||
|
* @param extSec Enable/disable extended security negotiation
|
||||||
* @return StringList
|
* @return StringList
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private final static StringList BuildNegotiatePacket(SMBPacket pkt, DialectSelector dlct, int pid)
|
private final static StringList BuildNegotiatePacket(SMBPacket pkt, DialectSelector dlct, int pid, boolean extSec)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Initialize the SMB packet header fields
|
// Initialize the SMB packet header fields
|
||||||
@@ -147,14 +148,14 @@ public final class AuthSessionFactory
|
|||||||
pkt.setCommand(PacketType.Negotiate);
|
pkt.setCommand(PacketType.Negotiate);
|
||||||
pkt.setProcessId(pid);
|
pkt.setProcessId(pid);
|
||||||
|
|
||||||
// If the NT dialect is enabled set the Unicode flag in the request flags
|
// If the NT dialect is enabled set the Unicode flag
|
||||||
|
|
||||||
int flags2 = 0;
|
int flags2 = 0;
|
||||||
|
|
||||||
if (dlct.hasDialect(Dialect.NT))
|
if (dlct.hasDialect(Dialect.NT))
|
||||||
flags2 += SMBPacket.FLG2_UNICODE;
|
flags2 += SMBPacket.FLG2_UNICODE;
|
||||||
|
|
||||||
if ( useExtendedSecurity())
|
if ( useExtendedSecurity() && extSec == true)
|
||||||
flags2 += SMBPacket.FLG2_EXTENDEDSECURITY;
|
flags2 += SMBPacket.FLG2_EXTENDEDSECURITY;
|
||||||
|
|
||||||
pkt.setFlags2(flags2);
|
pkt.setFlags2(flags2);
|
||||||
@@ -486,7 +487,7 @@ public final class AuthSessionFactory
|
|||||||
|
|
||||||
// Build the negotiate SMB dialect packet and exchange with the remote server
|
// Build the negotiate SMB dialect packet and exchange with the remote server
|
||||||
|
|
||||||
StringList diaList = BuildNegotiatePacket(pkt, selDialect, pid);
|
StringList diaList = BuildNegotiatePacket(pkt, selDialect, pid, shr.hasExtendedSecurityFlags());
|
||||||
pkt.ExchangeLowLevelSMB(netSession, pkt, true);
|
pkt.ExchangeLowLevelSMB(netSession, pkt, true);
|
||||||
|
|
||||||
// Determine the selected SMB dialect
|
// Determine the selected SMB dialect
|
||||||
|
@@ -1016,7 +1016,7 @@ public class AuthenticateSession
|
|||||||
*/
|
*/
|
||||||
public final void doSessionSetup(String userName, byte[] ascPwd, byte[] uniPwd) throws IOException, SMBException
|
public final void doSessionSetup(String userName, byte[] ascPwd, byte[] uniPwd) throws IOException, SMBException
|
||||||
{
|
{
|
||||||
doSessionSetup(null, userName, null, ascPwd, uniPwd);
|
doSessionSetup(null, userName, null, ascPwd, uniPwd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1029,7 +1029,7 @@ public class AuthenticateSession
|
|||||||
public final void doSessionSetup(Type3NTLMMessage type3Msg) throws IOException, SMBException
|
public final void doSessionSetup(Type3NTLMMessage type3Msg) throws IOException, SMBException
|
||||||
{
|
{
|
||||||
doSessionSetup(type3Msg.getDomain(), type3Msg.getUserName(), type3Msg.getWorkstation(),
|
doSessionSetup(type3Msg.getDomain(), type3Msg.getUserName(), type3Msg.getWorkstation(),
|
||||||
type3Msg.getLMHash(), type3Msg.getNTLMHash());
|
type3Msg.getLMHash(), type3Msg.getNTLMHash(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1040,11 +1040,13 @@ public class AuthenticateSession
|
|||||||
* @param wksName String
|
* @param wksName String
|
||||||
* @param ascPwd ASCII password hash
|
* @param ascPwd ASCII password hash
|
||||||
* @param uniPwd Unicode password hash
|
* @param uniPwd Unicode password hash
|
||||||
|
* @param vcNum Virtual circuit number
|
||||||
* @exception IOException If a network error occurs
|
* @exception IOException If a network error occurs
|
||||||
* @exception SMBException If a CIFS error occurs
|
* @exception SMBException If a CIFS error occurs
|
||||||
*/
|
*/
|
||||||
public final void doSessionSetup(String domain, String userName, String wksName,
|
public final void doSessionSetup(String domain, String userName, String wksName,
|
||||||
byte[] ascPwd, byte[] uniPwd) throws IOException, SMBException
|
byte[] ascPwd, byte[] uniPwd, int vcNum)
|
||||||
|
throws IOException, SMBException
|
||||||
{
|
{
|
||||||
// Check if we are using extended security
|
// Check if we are using extended security
|
||||||
|
|
||||||
@@ -1052,7 +1054,7 @@ public class AuthenticateSession
|
|||||||
{
|
{
|
||||||
// Run the second phase of the extended security session setup
|
// Run the second phase of the extended security session setup
|
||||||
|
|
||||||
doExtendedSessionSetupPhase2(domain, userName, wksName, ascPwd, uniPwd);
|
doExtendedSessionSetupPhase2(domain, userName, wksName, ascPwd, uniPwd, vcNum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,7 +1076,7 @@ public class AuthenticateSession
|
|||||||
pkt.setParameter(1, 0); // offset to next command
|
pkt.setParameter(1, 0); // offset to next command
|
||||||
pkt.setParameter(2, DefaultPacketSize);
|
pkt.setParameter(2, DefaultPacketSize);
|
||||||
pkt.setParameter(3, 1);
|
pkt.setParameter(3, 1);
|
||||||
pkt.setParameter(4, 0); // virtual circuit number
|
pkt.setParameter(4, vcNum);
|
||||||
pkt.setParameterLong(5, 0); // session key
|
pkt.setParameterLong(5, 0); // session key
|
||||||
|
|
||||||
// Set the share password length(s)
|
// Set the share password length(s)
|
||||||
@@ -1121,7 +1123,7 @@ public class AuthenticateSession
|
|||||||
pkt.packString("?", false);
|
pkt.packString("?", false);
|
||||||
|
|
||||||
pkt.packString("Java VM", false);
|
pkt.packString("Java VM", false);
|
||||||
pkt.packString("JLAN", false);
|
pkt.packString("Alfresco CIFS", false);
|
||||||
|
|
||||||
// Set the packet length
|
// Set the packet length
|
||||||
|
|
||||||
@@ -1175,7 +1177,7 @@ public class AuthenticateSession
|
|||||||
clbuf.append("Java VM");
|
clbuf.append("Java VM");
|
||||||
clbuf.append((char) 0x00);
|
clbuf.append((char) 0x00);
|
||||||
|
|
||||||
clbuf.append("JLAN");
|
clbuf.append("Alfresco CIFS");
|
||||||
clbuf.append((char) 0x00);
|
clbuf.append((char) 0x00);
|
||||||
|
|
||||||
// Copy the remaining data to the SMB packet
|
// Copy the remaining data to the SMB packet
|
||||||
@@ -1275,7 +1277,6 @@ public class AuthenticateSession
|
|||||||
|
|
||||||
if (getDialect() == Dialect.NT)
|
if (getDialect() == Dialect.NT)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Read the returned negotiate parameters, for NT dialect the parameters are not aligned
|
// Read the returned negotiate parameters, for NT dialect the parameters are not aligned
|
||||||
|
|
||||||
m_pkt.resetParameterPointer();
|
m_pkt.resetParameterPointer();
|
||||||
@@ -1324,7 +1325,7 @@ public class AuthenticateSession
|
|||||||
|
|
||||||
// Set the default flags for subsequent SMB requests
|
// Set the default flags for subsequent SMB requests
|
||||||
|
|
||||||
defFlags2 = SMBPacket.FLG2_LONGFILENAMES + SMBPacket.FLG2_UNICODE + SMBPacket.FLG2_LONGERRORCODE;
|
defFlags2 = SMBPacket.FLG2_LONGFILENAMES + SMBPacket.FLG2_UNICODE + SMBPacket.FLG2_LONGERRORCODE + SMBPacket.FLG2_SECURITYSIG;
|
||||||
|
|
||||||
if ( isUsingExtendedSecurity())
|
if ( isUsingExtendedSecurity())
|
||||||
defFlags2 += SMBPacket.FLG2_EXTENDEDSECURITY;
|
defFlags2 += SMBPacket.FLG2_EXTENDEDSECURITY;
|
||||||
@@ -1485,7 +1486,7 @@ public class AuthenticateSession
|
|||||||
// Pack the OS details
|
// Pack the OS details
|
||||||
|
|
||||||
pkt.packString("Java VM", true);
|
pkt.packString("Java VM", true);
|
||||||
pkt.packString("JLAN", true);
|
pkt.packString("Alfresco CIFS", true);
|
||||||
|
|
||||||
pkt.packString("", true);
|
pkt.packString("", true);
|
||||||
|
|
||||||
@@ -1555,11 +1556,12 @@ public class AuthenticateSession
|
|||||||
* @param wksName String
|
* @param wksName String
|
||||||
* @param lmPwd byte[]
|
* @param lmPwd byte[]
|
||||||
* @param ntlmPwd byte[]
|
* @param ntlmPwd byte[]
|
||||||
|
* @param vcNum int
|
||||||
* @exception IOException If a network error occurs
|
* @exception IOException If a network error occurs
|
||||||
* @eception SMBException If a CIFS error occurs
|
* @eception SMBException If a CIFS error occurs
|
||||||
*/
|
*/
|
||||||
private final void doExtendedSessionSetupPhase2(String domain, String userName, String wksName,
|
private final void doExtendedSessionSetupPhase2(String domain, String userName, String wksName,
|
||||||
byte[] lmPwd, byte[] ntlmPwd) throws IOException, SMBException
|
byte[] lmPwd, byte[] ntlmPwd, int vcNum) throws IOException, SMBException
|
||||||
{
|
{
|
||||||
// Check if the domain name has been specified, if not then use the domain name from the
|
// Check if the domain name has been specified, if not then use the domain name from the
|
||||||
// original connection details or the servers domain name
|
// original connection details or the servers domain name
|
||||||
@@ -1590,7 +1592,7 @@ public class AuthenticateSession
|
|||||||
pkt.setParameter(1, 0); // offset to next command
|
pkt.setParameter(1, 0); // offset to next command
|
||||||
pkt.setParameter(2, DefaultPacketSize);
|
pkt.setParameter(2, DefaultPacketSize);
|
||||||
pkt.setParameter(3, 1);
|
pkt.setParameter(3, 1);
|
||||||
pkt.setParameter(4, 0); // virtual circuit number
|
pkt.setParameter(4, vcNum);
|
||||||
pkt.setParameterLong(5, 0); // session key
|
pkt.setParameterLong(5, 0); // session key
|
||||||
|
|
||||||
// Clear the security blob length and reserved area
|
// Clear the security blob length and reserved area
|
||||||
@@ -1629,7 +1631,7 @@ public class AuthenticateSession
|
|||||||
// Pack the OS details
|
// Pack the OS details
|
||||||
|
|
||||||
pkt.packString("Java VM", true);
|
pkt.packString("Java VM", true);
|
||||||
pkt.packString("JLAN", true);
|
pkt.packString("Alfresco CIFS", true);
|
||||||
|
|
||||||
pkt.packString("", true);
|
pkt.packString("", true);
|
||||||
|
|
||||||
@@ -1645,4 +1647,5 @@ public class AuthenticateSession
|
|||||||
|
|
||||||
setGuest(pkt.getParameter(2) != 0 ? true : false);
|
setGuest(pkt.getParameter(2) != 0 ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.filesys.server.auth.passthru;
|
package org.alfresco.filesys.server.auth.passthru;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
@@ -33,14 +36,28 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
|||||||
import org.alfresco.filesys.server.SessionListener;
|
import org.alfresco.filesys.server.SessionListener;
|
||||||
import org.alfresco.filesys.server.SrvSession;
|
import org.alfresco.filesys.server.SrvSession;
|
||||||
import org.alfresco.filesys.server.auth.AuthContext;
|
import org.alfresco.filesys.server.auth.AuthContext;
|
||||||
|
import org.alfresco.filesys.server.auth.AuthenticatorException;
|
||||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||||
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
||||||
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.NTLM;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.NTLMMessage;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.TargetInfo;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.Type1NTLMMessage;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.Type2NTLMMessage;
|
||||||
|
import org.alfresco.filesys.server.auth.ntlm.Type3NTLMMessage;
|
||||||
import org.alfresco.filesys.server.config.InvalidConfigurationException;
|
import org.alfresco.filesys.server.config.InvalidConfigurationException;
|
||||||
import org.alfresco.filesys.server.config.ServerConfiguration;
|
import org.alfresco.filesys.server.config.ServerConfiguration;
|
||||||
import org.alfresco.filesys.server.core.SharedDevice;
|
import org.alfresco.filesys.server.core.SharedDevice;
|
||||||
|
import org.alfresco.filesys.smb.Capability;
|
||||||
|
import org.alfresco.filesys.smb.SMBStatus;
|
||||||
import org.alfresco.filesys.smb.server.SMBServer;
|
import org.alfresco.filesys.smb.server.SMBServer;
|
||||||
|
import org.alfresco.filesys.smb.server.SMBSrvException;
|
||||||
|
import org.alfresco.filesys.smb.server.SMBSrvPacket;
|
||||||
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
||||||
|
import org.alfresco.filesys.smb.server.VirtualCircuit;
|
||||||
|
import org.alfresco.filesys.util.DataPacker;
|
||||||
|
import org.alfresco.filesys.util.HexDump;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@@ -66,6 +83,18 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
public final static int MinSessionTmo = 2000; // 2 seconds
|
public final static int MinSessionTmo = 2000; // 2 seconds
|
||||||
public final static int MaxSessionTmo = 30000; // 30 seconds
|
public final static int MaxSessionTmo = 30000; // 30 seconds
|
||||||
|
|
||||||
|
// Passthru keep alive interval
|
||||||
|
|
||||||
|
public final static long PassthruKeepAliveInterval = 60000L; // 60 seconds
|
||||||
|
|
||||||
|
// NTLM flags mask, used to mask out features that are not supported
|
||||||
|
|
||||||
|
private static final int NTLM_FLAGS = NTLM.Flag56Bit +
|
||||||
|
NTLM.Flag128Bit +
|
||||||
|
NTLM.FlagLanManKey +
|
||||||
|
NTLM.FlagNegotiateNTLM +
|
||||||
|
NTLM.FlagNegotiateUnicode;
|
||||||
|
|
||||||
// Passthru servers used to authenticate users
|
// Passthru servers used to authenticate users
|
||||||
|
|
||||||
private PassthruServers m_passthruServers;
|
private PassthruServers m_passthruServers;
|
||||||
@@ -192,7 +221,7 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
// using the session that has already been setup.
|
// using the session that has already been setup.
|
||||||
|
|
||||||
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
||||||
authSess.doSessionSetup(client.getDomain(), client.getUserName(), null, client.getANSIPassword(), client.getPassword());
|
authSess.doSessionSetup(client.getDomain(), client.getUserName(), null, client.getANSIPassword(), client.getPassword(), 0);
|
||||||
|
|
||||||
// Check if the user has been logged on as a guest
|
// Check if the user has been logged on as a guest
|
||||||
|
|
||||||
@@ -311,51 +340,43 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
*/
|
*/
|
||||||
public AuthContext getAuthContext( SMBSrvSession sess)
|
public AuthContext getAuthContext( SMBSrvSession sess)
|
||||||
{
|
{
|
||||||
|
// Make sure the SMB server listener is installed
|
||||||
|
|
||||||
// Check for an SMB session
|
if ( m_server == null && sess instanceof SMBSrvSession)
|
||||||
|
{
|
||||||
|
SMBSrvSession smbSess = (SMBSrvSession) sess;
|
||||||
|
m_server = smbSess.getSMBServer();
|
||||||
|
|
||||||
|
// Install the server listener
|
||||||
|
|
||||||
|
m_server.addSessionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a connection to the authentication server, use normal session setup
|
||||||
|
|
||||||
AuthContext authCtx = null;
|
AuthContext authCtx = null;
|
||||||
|
|
||||||
// Check if the client is already authenticated, and it is not a null logon
|
|
||||||
|
|
||||||
if ( sess.hasAuthenticationContext() && sess.hasClientInformation() &&
|
|
||||||
sess.getClientInformation().getAuthenticationToken() != null &&
|
|
||||||
sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
|
|
||||||
{
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( logger.isDebugEnabled())
|
|
||||||
logger.debug("Re-using existing challenge, already authenticated");
|
|
||||||
|
|
||||||
// Return the previous challenge, user is already authenticated
|
|
||||||
|
|
||||||
return sess.getAuthenticationContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
AuthenticateSession authSess = m_passthruServers.openSession();
|
||||||
|
if (authSess != null)
|
||||||
|
{
|
||||||
|
|
||||||
// Open a connection to the authentication server
|
// Create an entry in the active sessions table for the new session
|
||||||
|
|
||||||
AuthenticateSession authSess = m_passthruServers.openSession();
|
PassthruDetails passDetails = new PassthruDetails(sess, authSess, false);
|
||||||
if (authSess != null)
|
m_sessions.put(sess.getUniqueId(), passDetails);
|
||||||
{
|
|
||||||
|
|
||||||
// Create an entry in the active sessions table for the new session
|
// Use the challenge key returned from the authentication server
|
||||||
|
|
||||||
PassthruDetails passDetails = new PassthruDetails(sess, authSess);
|
authCtx = new NTLanManAuthContext( authSess.getEncryptionKey());
|
||||||
m_sessions.put(sess.getUniqueId(), passDetails);
|
sess.setAuthenticationContext( authCtx);
|
||||||
|
|
||||||
// Use the challenge key returned from the authentication server
|
// DEBUG
|
||||||
|
|
||||||
authCtx = new NTLanManAuthContext( authSess.getEncryptionKey());
|
if (logger.isDebugEnabled())
|
||||||
sess.setAuthenticationContext( authCtx);
|
logger.debug("Passthru sessId=" + authSess.getSessionId() + ", auth ctx=" + authCtx);
|
||||||
|
}
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Passthru sessId=" + authSess.getSessionId() + ", auth ctx=" + authCtx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -370,6 +391,685 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
return authCtx;
|
return authCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the CIFS negotiate response packet, the authenticator should add authentication specific fields
|
||||||
|
* to the response.
|
||||||
|
*
|
||||||
|
* @param sess SMBSrvSession
|
||||||
|
* @param respPkt SMBSrvPacket
|
||||||
|
* @param extendedSecurity boolean
|
||||||
|
* @exception AuthenticatorException
|
||||||
|
*/
|
||||||
|
public void generateNegotiateResponse(SMBSrvSession sess, SMBSrvPacket respPkt, boolean extendedSecurity)
|
||||||
|
throws AuthenticatorException
|
||||||
|
{
|
||||||
|
// If the client does not support extended security then return a standard negotiate response
|
||||||
|
// with an 8 byte challenge
|
||||||
|
|
||||||
|
if ( extendedSecurity == false)
|
||||||
|
{
|
||||||
|
super.generateNegotiateResponse( sess, respPkt, extendedSecurity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the extended security negotiation flag is set
|
||||||
|
|
||||||
|
if (( respPkt.getFlags2() & SMBSrvPacket.FLG2_EXTENDEDSECURITY) == 0)
|
||||||
|
respPkt.setFlags2( respPkt.getFlags2() + SMBSrvPacket.FLG2_EXTENDEDSECURITY);
|
||||||
|
|
||||||
|
// Get the negotiate response byte area position
|
||||||
|
|
||||||
|
int pos = respPkt.getByteOffset();
|
||||||
|
byte[] buf = respPkt.getBuffer();
|
||||||
|
|
||||||
|
// Pack the CIFS server GUID into the negotiate response
|
||||||
|
|
||||||
|
UUID serverGUID = sess.getSMBServer().getServerGUID();
|
||||||
|
|
||||||
|
DataPacker.putIntelLong( serverGUID.getLeastSignificantBits(), buf, pos);
|
||||||
|
DataPacker.putIntelLong( serverGUID.getMostSignificantBits(), buf, pos + 8);
|
||||||
|
|
||||||
|
pos += 16;
|
||||||
|
|
||||||
|
// Set the negotiate response length
|
||||||
|
|
||||||
|
respPkt.setByteCount(pos - respPkt.getByteOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the CIFS session setup request packet and build the session setup response
|
||||||
|
*
|
||||||
|
* @param sess SMBSrvSession
|
||||||
|
* @param reqPkt SMBSrvPacket
|
||||||
|
* @param respPkt SMBSrvPacket
|
||||||
|
* @exception SMBSrvException
|
||||||
|
*/
|
||||||
|
public void processSessionSetup(SMBSrvSession sess, SMBSrvPacket reqPkt, SMBSrvPacket respPkt)
|
||||||
|
throws SMBSrvException
|
||||||
|
{
|
||||||
|
// Check that the received packet looks like a valid NT session setup andX request
|
||||||
|
|
||||||
|
if (reqPkt.checkPacketIsValid(12, 0) == false)
|
||||||
|
throw new SMBSrvException(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||||
|
|
||||||
|
// Check if the request is using security blobs or the older hashed password format
|
||||||
|
|
||||||
|
if ( reqPkt.getParameterCount() == 13)
|
||||||
|
{
|
||||||
|
// Process the standard password session setup
|
||||||
|
|
||||||
|
super.processSessionSetup( sess, reqPkt, respPkt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the session details
|
||||||
|
|
||||||
|
int maxBufSize = reqPkt.getParameter(2);
|
||||||
|
int maxMpx = reqPkt.getParameter(3);
|
||||||
|
int vcNum = reqPkt.getParameter(4);
|
||||||
|
int secBlobLen = reqPkt.getParameter(7);
|
||||||
|
int capabs = reqPkt.getParameterLong(10);
|
||||||
|
|
||||||
|
// Extract the client details from the session setup request
|
||||||
|
|
||||||
|
int dataPos = reqPkt.getByteOffset();
|
||||||
|
byte[] buf = reqPkt.getBuffer();
|
||||||
|
|
||||||
|
// Determine if ASCII or unicode strings are being used
|
||||||
|
|
||||||
|
boolean isUni = reqPkt.isUnicode();
|
||||||
|
|
||||||
|
// Make a note of the security blob position
|
||||||
|
|
||||||
|
int secBlobPos = dataPos;
|
||||||
|
|
||||||
|
// Extract the clients primary domain name string
|
||||||
|
|
||||||
|
dataPos += secBlobLen;
|
||||||
|
reqPkt.setPosition( dataPos);
|
||||||
|
|
||||||
|
String domain = "";
|
||||||
|
|
||||||
|
if (reqPkt.hasMoreData()) {
|
||||||
|
|
||||||
|
// Extract the callers domain name
|
||||||
|
|
||||||
|
domain = reqPkt.unpackString(isUni);
|
||||||
|
|
||||||
|
if (domain == null)
|
||||||
|
throw new SMBSrvException(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the clients native operating system
|
||||||
|
|
||||||
|
String clientOS = "";
|
||||||
|
|
||||||
|
if (reqPkt.hasMoreData()) {
|
||||||
|
|
||||||
|
// Extract the callers operating system name
|
||||||
|
|
||||||
|
clientOS = reqPkt.unpackString(isUni);
|
||||||
|
|
||||||
|
if (clientOS == null)
|
||||||
|
throw new SMBSrvException( SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the client maximum buffer size, maximum multiplexed requests count and client capability flags
|
||||||
|
|
||||||
|
sess.setClientMaximumBufferSize(maxBufSize != 0 ? maxBufSize : SMBSrvSession.DefaultBufferSize);
|
||||||
|
sess.setClientMaximumMultiplex(maxMpx);
|
||||||
|
sess.setClientCapabilities(capabs);
|
||||||
|
|
||||||
|
// Create the client information and store in the session
|
||||||
|
|
||||||
|
ClientInfo client = new ClientInfo();
|
||||||
|
client.setDomain(domain);
|
||||||
|
client.setOperatingSystem(clientOS);
|
||||||
|
|
||||||
|
client.setLogonType( ClientInfo.LogonNormal);
|
||||||
|
|
||||||
|
// Set the remote address, if available
|
||||||
|
|
||||||
|
if ( sess.hasRemoteAddress())
|
||||||
|
client.setClientAddress(sess.getRemoteAddress().getHostAddress());
|
||||||
|
|
||||||
|
// Set the process id for this client, for multi-stage logons
|
||||||
|
|
||||||
|
client.setProcessId( reqPkt.getProcessId());
|
||||||
|
|
||||||
|
// Get the current sesion setup object, or null
|
||||||
|
|
||||||
|
Object setupObj = sess.getSetupObject( client.getProcessId());
|
||||||
|
|
||||||
|
// Process the security blob
|
||||||
|
|
||||||
|
byte[] respBlob = null;
|
||||||
|
boolean isNTLMSSP = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// Check if the blob has the NTLMSSP signature
|
||||||
|
|
||||||
|
if ( secBlobLen >= NTLM.Signature.length) {
|
||||||
|
|
||||||
|
// Check for the NTLMSSP signature
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
while ( idx < NTLM.Signature.length && buf[secBlobPos + idx] == NTLM.Signature[ idx])
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if ( idx == NTLM.Signature.length)
|
||||||
|
isNTLMSSP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the security blob
|
||||||
|
|
||||||
|
if ( isNTLMSSP == true)
|
||||||
|
{
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("NT Session setup NTLMSSP, MID=" + reqPkt.getMultiplexId() + ", UID=" + reqPkt.getUserId() + ", PID=" + reqPkt.getProcessId());
|
||||||
|
|
||||||
|
// Process an NTLMSSP security blob
|
||||||
|
|
||||||
|
respBlob = doNtlmsspSessionSetup( sess, client, buf, secBlobPos, secBlobLen, isUni);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid blob type
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SMBSrvException ex)
|
||||||
|
{
|
||||||
|
// Cleanup any stored context
|
||||||
|
|
||||||
|
sess.removeSetupObject( client.getProcessId());
|
||||||
|
|
||||||
|
// Rethrow the exception
|
||||||
|
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_NEGOTIATE))
|
||||||
|
logger.debug("User " + client.getUserName() + " logged on " + (client != null ? " (type " + client.getLogonTypeString() + ")" : ""));
|
||||||
|
|
||||||
|
// Update the client information if not already set
|
||||||
|
|
||||||
|
if ( sess.getClientInformation() == null ||
|
||||||
|
sess.getClientInformation().getUserName().length() == 0) {
|
||||||
|
|
||||||
|
// Set the client details for the session
|
||||||
|
|
||||||
|
sess.setClientInformation(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the response blob length, it can be null
|
||||||
|
|
||||||
|
int respLen = respBlob != null ? respBlob.length : 0;
|
||||||
|
|
||||||
|
// Check if there is/was a session setup object stored in the session, this indicates a multi-stage session
|
||||||
|
// setup so set the status code accordingly
|
||||||
|
|
||||||
|
boolean loggedOn = false;
|
||||||
|
|
||||||
|
if ( isNTLMSSP == true || sess.hasSetupObject( client.getProcessId()) || setupObj != null)
|
||||||
|
{
|
||||||
|
// NTLMSSP has two stages, if there is a stored setup object then indicate more processing
|
||||||
|
// required
|
||||||
|
|
||||||
|
if ( sess.hasSetupObject( client.getProcessId()))
|
||||||
|
respPkt.setLongErrorCode( SMBStatus.NTMoreProcessingRequired);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
respPkt.setLongErrorCode( SMBStatus.NTSuccess);
|
||||||
|
|
||||||
|
// Indicate that the user is logged on
|
||||||
|
|
||||||
|
loggedOn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
respPkt.setParameterCount(4);
|
||||||
|
respPkt.setParameter(0, 0xFF); // No chained response
|
||||||
|
respPkt.setParameter(1, 0); // Offset to chained response
|
||||||
|
|
||||||
|
respPkt.setParameter(2, 0); // Action
|
||||||
|
respPkt.setParameter(3, respLen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Build a completed session setup response
|
||||||
|
|
||||||
|
respPkt.setLongErrorCode( SMBStatus.NTSuccess);
|
||||||
|
|
||||||
|
// Build the session setup response SMB
|
||||||
|
|
||||||
|
respPkt.setParameterCount(12);
|
||||||
|
respPkt.setParameter(0, 0xFF); // No chained response
|
||||||
|
respPkt.setParameter(1, 0); // Offset to chained response
|
||||||
|
|
||||||
|
respPkt.setParameter(2, SMBSrvSession.DefaultBufferSize);
|
||||||
|
respPkt.setParameter(3, SMBSrvSession.NTMaxMultiplexed);
|
||||||
|
respPkt.setParameter(4, 0); // virtual circuit number
|
||||||
|
respPkt.setParameterLong(5, 0); // session key
|
||||||
|
respPkt.setParameter(7, respLen);
|
||||||
|
// security blob length
|
||||||
|
respPkt.setParameterLong(8, 0); // reserved
|
||||||
|
respPkt.setParameterLong(10, getServerCapabilities());
|
||||||
|
|
||||||
|
// Indicate that the user is logged on
|
||||||
|
|
||||||
|
loggedOn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user is logged on then allocate a virtual circuit
|
||||||
|
|
||||||
|
int uid = 0;
|
||||||
|
|
||||||
|
if ( loggedOn == true) {
|
||||||
|
|
||||||
|
// Clear any stored session setup object for the logon
|
||||||
|
|
||||||
|
sess.removeSetupObject( client.getProcessId());
|
||||||
|
|
||||||
|
// Create a virtual circuit for the new logon
|
||||||
|
|
||||||
|
VirtualCircuit vc = new VirtualCircuit( vcNum, client);
|
||||||
|
uid = sess.addVirtualCircuit( vc);
|
||||||
|
|
||||||
|
if ( uid == VirtualCircuit.InvalidUID)
|
||||||
|
{
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled() && sess.hasDebug( SMBSrvSession.DBG_NEGOTIATE))
|
||||||
|
logger.debug("Failed to allocate UID for virtual circuit, " + vc);
|
||||||
|
|
||||||
|
// Failed to allocate a UID
|
||||||
|
|
||||||
|
throw new SMBSrvException(SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
|
||||||
|
}
|
||||||
|
else if ( logger.isDebugEnabled() && sess.hasDebug( SMBSrvSession.DBG_NEGOTIATE)) {
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
logger.debug("Allocated UID=" + uid + " for VC=" + vc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common session setup response
|
||||||
|
|
||||||
|
respPkt.setCommand( reqPkt.getCommand());
|
||||||
|
respPkt.setByteCount(0);
|
||||||
|
|
||||||
|
respPkt.setTreeId( 0);
|
||||||
|
respPkt.setUserId( uid);
|
||||||
|
|
||||||
|
// Set the various flags
|
||||||
|
|
||||||
|
int flags = respPkt.getFlags();
|
||||||
|
flags &= ~SMBSrvPacket.FLG_CASELESS;
|
||||||
|
respPkt.setFlags(flags);
|
||||||
|
|
||||||
|
int flags2 = SMBSrvPacket.FLG2_LONGFILENAMES + SMBSrvPacket.FLG2_EXTENDEDSECURITY + SMBSrvPacket.FLG2_LONGERRORCODE;
|
||||||
|
if ( isUni)
|
||||||
|
flags2 += SMBSrvPacket.FLG2_UNICODE;
|
||||||
|
respPkt.setFlags2( flags2);
|
||||||
|
|
||||||
|
// Pack the security blob
|
||||||
|
|
||||||
|
int pos = respPkt.getByteOffset();
|
||||||
|
buf = respPkt.getBuffer();
|
||||||
|
|
||||||
|
if ( respBlob != null)
|
||||||
|
{
|
||||||
|
System.arraycopy( respBlob, 0, buf, pos, respBlob.length);
|
||||||
|
pos += respBlob.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack the OS, dialect and domain name strings
|
||||||
|
|
||||||
|
if ( isUni)
|
||||||
|
pos = DataPacker.wordAlign(pos);
|
||||||
|
|
||||||
|
pos = DataPacker.putString("Java", buf, pos, true, isUni);
|
||||||
|
pos = DataPacker.putString("Alfresco CIFS Server " + sess.getServer().isVersion(), buf, pos, true, isUni);
|
||||||
|
pos = DataPacker.putString(sess.getServer().getConfiguration().getDomainName(), buf, pos, true, isUni);
|
||||||
|
|
||||||
|
respPkt.setByteCount(pos - respPkt.getByteOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an NTLMSSP security blob
|
||||||
|
*
|
||||||
|
* @param sess SMBSrvSession
|
||||||
|
* @param client ClientInfo
|
||||||
|
* @param secbuf byte[]
|
||||||
|
* @param secpos int
|
||||||
|
* @param seclen int
|
||||||
|
* @param unicode boolean
|
||||||
|
* @exception SMBSrvException
|
||||||
|
*/
|
||||||
|
private final byte[] doNtlmsspSessionSetup( SMBSrvSession sess, ClientInfo client,
|
||||||
|
byte[] secbuf, int secpos, int seclen, boolean unicode) throws SMBSrvException
|
||||||
|
{
|
||||||
|
// Determine the NTLmSSP message type
|
||||||
|
|
||||||
|
int msgType = NTLMMessage.isNTLMType( secbuf, secpos);
|
||||||
|
byte[] respBlob = null;
|
||||||
|
|
||||||
|
if ( msgType == -1)
|
||||||
|
{
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Invalid NTLMSSP token received");
|
||||||
|
logger.debug(" Token=" + HexDump.hexString( secbuf, secpos, seclen, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a logon failure status
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a type 1 NTLMSSP message
|
||||||
|
|
||||||
|
else if ( msgType == NTLM.Type1)
|
||||||
|
{
|
||||||
|
// Create the type 1 NTLM message from the token
|
||||||
|
|
||||||
|
Type1NTLMMessage type1Msg = new Type1NTLMMessage( secbuf, secpos, seclen);
|
||||||
|
|
||||||
|
// Build the type 2 NTLM response message
|
||||||
|
//
|
||||||
|
// Get the flags from the client request and mask out unsupported features
|
||||||
|
|
||||||
|
int ntlmFlags = type1Msg.getFlags() & NTLM_FLAGS;
|
||||||
|
|
||||||
|
// Generate a challenge for the response
|
||||||
|
|
||||||
|
NTLanManAuthContext ntlmCtx = (NTLanManAuthContext) getAuthContext( sess);
|
||||||
|
|
||||||
|
// Build a type2 message to send back to the client, containing the challenge
|
||||||
|
|
||||||
|
String domain = sess.getSMBServer().getServerName();
|
||||||
|
|
||||||
|
List<TargetInfo> tList = new ArrayList<TargetInfo>();
|
||||||
|
|
||||||
|
tList.add(new TargetInfo(NTLM.TargetDomain, domain));
|
||||||
|
tList.add(new TargetInfo(NTLM.TargetServer, sess.getServerName()));
|
||||||
|
tList.add(new TargetInfo(NTLM.TargetDNSDomain, domain));
|
||||||
|
tList.add(new TargetInfo(NTLM.TargetFullDNS, domain));
|
||||||
|
|
||||||
|
ntlmFlags = NTLM.FlagChallengeAccept + NTLM.FlagRequestTarget +
|
||||||
|
NTLM.FlagNegotiateNTLM + NTLM.FlagNegotiateUnicode +
|
||||||
|
NTLM.FlagKeyExchange + NTLM.FlagTargetInfo + NTLM.Flag56Bit;
|
||||||
|
|
||||||
|
// NTLM.FlagAlwaysSign + NTLM.FlagNegotiateSign +
|
||||||
|
|
||||||
|
Type2NTLMMessage type2Msg = new Type2NTLMMessage();
|
||||||
|
|
||||||
|
type2Msg.buildType2(ntlmFlags, domain, ntlmCtx.getChallenge(), null, tList);
|
||||||
|
|
||||||
|
// Store the type 2 message in the session until the session setup is complete
|
||||||
|
|
||||||
|
sess.setSetupObject( client.getProcessId(), type2Msg);
|
||||||
|
|
||||||
|
// Set the response blob using the type 2 message
|
||||||
|
|
||||||
|
respBlob = type2Msg.getBytes();
|
||||||
|
}
|
||||||
|
else if ( msgType == NTLM.Type3)
|
||||||
|
{
|
||||||
|
// Create the type 3 NTLM message from the token
|
||||||
|
|
||||||
|
Type3NTLMMessage type3Msg = new Type3NTLMMessage( secbuf, secpos, seclen, unicode);
|
||||||
|
|
||||||
|
// Make sure a type 2 message was stored in the first stage of the session setup
|
||||||
|
|
||||||
|
if ( sess.hasSetupObject( client.getProcessId()) == false || sess.getSetupObject( client.getProcessId()) instanceof Type2NTLMMessage == false)
|
||||||
|
{
|
||||||
|
// Clear the setup object
|
||||||
|
|
||||||
|
sess.removeSetupObject( client.getProcessId());
|
||||||
|
|
||||||
|
// Return a logon failure
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if the client sent us NTLMv1 or NTLMv2
|
||||||
|
|
||||||
|
if ( type3Msg.hasFlag( NTLM.Flag128Bit) && type3Msg.hasFlag( NTLM.FlagNTLM2Key))
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Received NTLMSSP/NTLMv2, not supported");
|
||||||
|
|
||||||
|
// Return a logon failure
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Looks like an NTLMv1 blob
|
||||||
|
|
||||||
|
doNTLMv1Logon( sess, client, type3Msg);
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Logged on using NTLMSSP/NTLMv1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the response blob
|
||||||
|
|
||||||
|
return respBlob;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an NTLMv1 logon using the NTLMSSP type3 message
|
||||||
|
*
|
||||||
|
* @param sess SMBSrvSession
|
||||||
|
* @param client ClientInfo
|
||||||
|
* @param type3Msg Type3NTLMMessage
|
||||||
|
* @exception SMBSrvException
|
||||||
|
*/
|
||||||
|
private final void doNTLMv1Logon(SMBSrvSession sess, ClientInfo client, Type3NTLMMessage type3Msg)
|
||||||
|
throws SMBSrvException
|
||||||
|
{
|
||||||
|
// Get the type 2 message that contains the challenge sent to the client
|
||||||
|
|
||||||
|
Type2NTLMMessage type2Msg = (Type2NTLMMessage) sess.getSetupObject( client.getProcessId());
|
||||||
|
sess.removeSetupObject( client.getProcessId());
|
||||||
|
|
||||||
|
// Get the NTLM logon details
|
||||||
|
|
||||||
|
String userName = type3Msg.getUserName();
|
||||||
|
|
||||||
|
// Check for a null logon
|
||||||
|
|
||||||
|
if ( userName.length() == 0)
|
||||||
|
{
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Null logon");
|
||||||
|
|
||||||
|
// Indicate a null logon in the client information
|
||||||
|
|
||||||
|
client.setLogonType( ClientInfo.LogonNull);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the active authentication session details for the server session
|
||||||
|
|
||||||
|
PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
|
||||||
|
|
||||||
|
if (passDetails != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Authenticate the user by passing the hashed password to the authentication server
|
||||||
|
// using the session that has already been setup.
|
||||||
|
|
||||||
|
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
||||||
|
authSess.doSessionSetup( type3Msg.getDomain(), userName, null, type3Msg.getLMHash(), type3Msg.getNTLMHash(), 0);
|
||||||
|
|
||||||
|
// Check if the user has been logged on as a guest
|
||||||
|
|
||||||
|
if (authSess.isGuest())
|
||||||
|
{
|
||||||
|
// Check if the local server allows guest access
|
||||||
|
|
||||||
|
if (allowGuest() == true)
|
||||||
|
{
|
||||||
|
// Get a guest authentication token
|
||||||
|
|
||||||
|
doGuestLogon( client, sess);
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("Passthru authenticate user=" + userName + ", GUEST");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Wrap the service calls in a transaction
|
||||||
|
|
||||||
|
UserTransaction tx = m_transactionService.getUserTransaction( false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Start the transaction
|
||||||
|
|
||||||
|
tx.begin();
|
||||||
|
|
||||||
|
// Map the passthru username to an Alfresco person
|
||||||
|
|
||||||
|
NodeRef userNode = m_personService.getPerson(userName);
|
||||||
|
if ( userNode != null)
|
||||||
|
{
|
||||||
|
// Get the person name and use that as the current user to line up with permission checks
|
||||||
|
|
||||||
|
String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
|
||||||
|
m_authComponent.setCurrentUser(personName);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Setting current user using person " + personName + " (username " + userName + ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set using the user name
|
||||||
|
|
||||||
|
m_authComponent.setCurrentUser( userName);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Setting current user using username " + userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the authentication token and store
|
||||||
|
|
||||||
|
client.setAuthenticationToken( m_authComponent.getCurrentAuthentication());
|
||||||
|
|
||||||
|
// Indicate that the client is logged on
|
||||||
|
|
||||||
|
client.setLogonType( ClientInfo.LogonNormal);
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("Passthru authenticate user=" + userName + ", FULL");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Commit the transaction
|
||||||
|
|
||||||
|
if ( tx != null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
tx.commit();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Sink it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the client details
|
||||||
|
|
||||||
|
client.setDomain( type3Msg.getDomain());
|
||||||
|
client.setUserName( userName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
logger.error(ex.getMessage());
|
||||||
|
|
||||||
|
// Indicate logon failure
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTErr, SMBStatus.NTLogonFailure);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Remove the passthru session from the active list
|
||||||
|
|
||||||
|
m_sessions.remove(sess.getUniqueId());
|
||||||
|
|
||||||
|
// Close the passthru authentication session
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// Close the authentication session
|
||||||
|
|
||||||
|
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
||||||
|
authSess.CloseSession();
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
logger.error("Passthru error closing session (auth user)", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug(" No PassthruDetails for " + sess.getUniqueId());
|
||||||
|
|
||||||
|
// Indicate logon failure
|
||||||
|
|
||||||
|
throw new SMBSrvException( SMBStatus.NTErr, SMBStatus.NTLogonFailure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialzie the authenticator
|
* Initialzie the authenticator
|
||||||
*
|
*
|
||||||
@@ -510,6 +1210,18 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
smbServer.addSessionListener(this);
|
smbServer.addSessionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the server capability flags
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public int getServerCapabilities()
|
||||||
|
{
|
||||||
|
return Capability.Unicode + Capability.RemoteAPIs + Capability.NTSMBs + Capability.NTFind +
|
||||||
|
Capability.NTStatus + Capability.LargeFiles + Capability.LargeRead + Capability.LargeWrite +
|
||||||
|
Capability.ExtendedSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the authenticator, perform cleanup
|
* Close the authenticator, perform cleanup
|
||||||
*/
|
*/
|
||||||
@@ -582,48 +1294,37 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL
|
|||||||
*/
|
*/
|
||||||
public void sessionLoggedOn(SrvSession sess)
|
public void sessionLoggedOn(SrvSession sess)
|
||||||
{
|
{
|
||||||
|
// Check if there is an active session to the authentication server for this local
|
||||||
|
// session
|
||||||
|
|
||||||
// Check if the client information has an empty user name, if so then do not close the
|
PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
|
||||||
// authentication session
|
|
||||||
|
|
||||||
if (sess.hasClientInformation() && sess.getClientInformation().getUserName() != null
|
if (passDetails != null && passDetails.hasKeepAlive() == false)
|
||||||
&& sess.getClientInformation().getUserName().length() > 0)
|
|
||||||
{
|
{
|
||||||
|
// Remove the passthru session from the active list
|
||||||
|
|
||||||
// Check if there is an active session to the authentication server for this local
|
m_sessions.remove(sess.getUniqueId());
|
||||||
// session
|
|
||||||
|
|
||||||
PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
|
// Close the passthru authentication session
|
||||||
|
|
||||||
if (passDetails != null)
|
try
|
||||||
|
{
|
||||||
|
// Close the authentication session
|
||||||
|
|
||||||
|
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
||||||
|
authSess.CloseSession();
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Remove the passthru session from the active list
|
// Debug
|
||||||
|
|
||||||
m_sessions.remove(sess.getUniqueId());
|
logger.error("Passthru error closing session (logon)", ex);
|
||||||
|
|
||||||
// Close the passthru authentication session
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
// Close the authentication session
|
|
||||||
|
|
||||||
AuthenticateSession authSess = passDetails.getAuthenticateSession();
|
|
||||||
authSess.CloseSession();
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Debug
|
|
||||||
|
|
||||||
logger.error("Passthru error closing session (logon)", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,6 @@ import org.alfresco.filesys.server.SrvSession;
|
|||||||
*/
|
*/
|
||||||
class PassthruDetails
|
class PassthruDetails
|
||||||
{
|
{
|
||||||
|
|
||||||
// Server session
|
// Server session
|
||||||
|
|
||||||
private SrvSession m_sess;
|
private SrvSession m_sess;
|
||||||
@@ -43,6 +42,10 @@ class PassthruDetails
|
|||||||
|
|
||||||
private AuthenticateSession m_authSess;
|
private AuthenticateSession m_authSess;
|
||||||
|
|
||||||
|
// Flag to indicate if session should be kept alive
|
||||||
|
|
||||||
|
private boolean m_keepAlive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor
|
* Class constructor
|
||||||
*
|
*
|
||||||
@@ -55,6 +58,21 @@ class PassthruDetails
|
|||||||
m_authSess = authSess;
|
m_authSess = authSess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* @param sess SrvSession
|
||||||
|
* @param authSess AuthenticateSession
|
||||||
|
* @param keepAlive boolean
|
||||||
|
*/
|
||||||
|
public PassthruDetails(SrvSession sess, AuthenticateSession authSess, boolean keepAlive)
|
||||||
|
{
|
||||||
|
m_sess = sess;
|
||||||
|
m_authSess = authSess;
|
||||||
|
|
||||||
|
m_keepAlive = keepAlive;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the session details
|
* Return the session details
|
||||||
*
|
*
|
||||||
@@ -74,4 +92,14 @@ class PassthruDetails
|
|||||||
{
|
{
|
||||||
return m_authSess;
|
return m_authSess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the authentication session should be kept alive
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public final boolean hasKeepAlive()
|
||||||
|
{
|
||||||
|
return m_keepAlive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -306,16 +306,16 @@ public class PassthruServers
|
|||||||
*/
|
*/
|
||||||
public final AuthenticateSession openSession()
|
public final AuthenticateSession openSession()
|
||||||
{
|
{
|
||||||
return openSession( 0);
|
return openSession( false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a new session to an authentication server
|
* Open a new session to an authentication server
|
||||||
*
|
*
|
||||||
* @param extFlags int
|
* @param useExtSec boolean
|
||||||
* @return AuthenticateSession
|
* @return AuthenticateSession
|
||||||
*/
|
*/
|
||||||
public final AuthenticateSession openSession(int extFlags)
|
public final AuthenticateSession openSession(boolean useExtSec)
|
||||||
{
|
{
|
||||||
// Get the details of an authentication server to connect to
|
// Get the details of an authentication server to connect to
|
||||||
|
|
||||||
@@ -331,7 +331,8 @@ public class PassthruServers
|
|||||||
// Open a new authentication session to the server
|
// Open a new authentication session to the server
|
||||||
|
|
||||||
PCShare authShare = new PCShare(passthruServer.getAddress().getHostAddress(), "IPC$", "", "");
|
PCShare authShare = new PCShare(passthruServer.getAddress().getHostAddress(), "IPC$", "", "");
|
||||||
authShare.setExtendedSecurityFlags( extFlags);
|
if ( useExtSec == true)
|
||||||
|
authShare.setExtendedSecurityFlags( SMBPacket.FLG2_EXTENDEDSECURITY);
|
||||||
|
|
||||||
AuthenticateSession authSess = null;
|
AuthenticateSession authSess = null;
|
||||||
|
|
||||||
|
@@ -88,6 +88,7 @@ public class SMBPacket
|
|||||||
|
|
||||||
public static final int FLG2_LONGFILENAMES = 0x0001;
|
public static final int FLG2_LONGFILENAMES = 0x0001;
|
||||||
public static final int FLG2_EXTENDEDATTRIB = 0x0002;
|
public static final int FLG2_EXTENDEDATTRIB = 0x0002;
|
||||||
|
public static final int FLG2_SECURITYSIG = 0x0004;
|
||||||
public static final int FLG2_EXTENDEDSECURITY = 0x0800;
|
public static final int FLG2_EXTENDEDSECURITY = 0x0800;
|
||||||
public static final int FLG2_READIFEXE = 0x2000;
|
public static final int FLG2_READIFEXE = 0x2000;
|
||||||
public static final int FLG2_LONGERRORCODE = 0x4000;
|
public static final int FLG2_LONGERRORCODE = 0x4000;
|
||||||
@@ -589,6 +590,16 @@ public class SMBPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get the SMB signing value, as a long value
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public final long getSignature()
|
||||||
|
{
|
||||||
|
return DataPacker.getIntelLong( m_smbbuf, SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Get the tree identifier (TID)
|
* Get the tree identifier (TID)
|
||||||
*
|
*
|
||||||
* @return Tree identifier (TID)
|
* @return Tree identifier (TID)
|
||||||
@@ -1131,6 +1142,16 @@ public class SMBPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Set a long error code (NT status code)
|
||||||
|
*
|
||||||
|
* @param sts int
|
||||||
|
*/
|
||||||
|
public final void setLongErrorCode(int lsts)
|
||||||
|
{
|
||||||
|
DataPacker.putIntelInt(lsts, m_smbbuf, ERRORCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Set the SMB flags value.
|
* Set the SMB flags value.
|
||||||
*
|
*
|
||||||
* @param flg SMB flags value.
|
* @param flg SMB flags value.
|
||||||
@@ -1225,6 +1246,38 @@ public class SMBPacket
|
|||||||
DataPacker.putIntelShort(sid, m_smbbuf, SID);
|
DataPacker.putIntelShort(sid, m_smbbuf, SID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the SMB signing signature
|
||||||
|
*
|
||||||
|
* @param ival int
|
||||||
|
*/
|
||||||
|
public final void setSignature( int ival)
|
||||||
|
{
|
||||||
|
DataPacker.putIntelInt( ival, m_smbbuf, SIGNATURE);
|
||||||
|
DataPacker.putZeros( m_smbbuf, SIGNATURE + 4, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the SMB signing signature
|
||||||
|
*
|
||||||
|
* @param lval long
|
||||||
|
*/
|
||||||
|
public final void setSignature( long lval)
|
||||||
|
{
|
||||||
|
DataPacker.putIntelLong( lval, m_smbbuf, SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the SMB signing signature
|
||||||
|
*
|
||||||
|
* @param byts byte[]
|
||||||
|
* @param offset int
|
||||||
|
*/
|
||||||
|
public final void setSignature( byte[] byts, int offset)
|
||||||
|
{
|
||||||
|
System.arraycopy( byts, offset, m_smbbuf, SIGNATURE, 8);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the tree identifier (TID)
|
* Set the tree identifier (TID)
|
||||||
*
|
*
|
||||||
|
@@ -1254,18 +1254,37 @@ public class ServerConfiguration extends AbstractLifecycleBean
|
|||||||
String lanaStr = elem.getAttribute("lana");
|
String lanaStr = elem.getAttribute("lana");
|
||||||
if (lanaStr != null && lanaStr.length() > 0)
|
if (lanaStr != null && lanaStr.length() > 0)
|
||||||
{
|
{
|
||||||
|
// Check if the LANA has been specified as an IP address or adapter name
|
||||||
// Validate the LANA number
|
|
||||||
|
|
||||||
int lana = -1;
|
int lana = -1;
|
||||||
|
|
||||||
try
|
if ( IPAddress.isNumericAddress( lanaStr))
|
||||||
{
|
{
|
||||||
lana = Integer.parseInt(lanaStr);
|
|
||||||
|
// Convert the IP address to a LANA id
|
||||||
|
|
||||||
|
lana = Win32NetBIOS.getLANAForIPAddress( lanaStr);
|
||||||
|
if ( lana == -1)
|
||||||
|
throw new AlfrescoRuntimeException( "Failed to convert IP address " + lanaStr + " to a LANA");
|
||||||
}
|
}
|
||||||
catch (NumberFormatException ex)
|
else if ( lanaStr.length() > 1 && Character.isLetter( lanaStr.charAt( 0))) {
|
||||||
{
|
|
||||||
throw new AlfrescoRuntimeException("Invalid win32 NetBIOS LANA specified");
|
// Convert the network adapter to a LANA id
|
||||||
|
|
||||||
|
lana = Win32NetBIOS.getLANAForAdapterName( lanaStr);
|
||||||
|
if ( lana == -1)
|
||||||
|
throw new AlfrescoRuntimeException( "Failed to convert network adapter " + lanaStr + " to a LANA");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lana = Integer.parseInt(lanaStr);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException ex)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Invalid win32 NetBIOS LANA specified");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LANA should be in the range 0-255
|
// LANA should be in the range 0-255
|
||||||
@@ -2265,8 +2284,8 @@ public class ServerConfiguration extends AbstractLifecycleBean
|
|||||||
{
|
{
|
||||||
// Check if the appropriate authentication component type is configured
|
// Check if the appropriate authentication component type is configured
|
||||||
|
|
||||||
if ( ntlmMode != NTLMMode.NONE)
|
if ( ntlmMode == NTLMMode.MD4_PROVIDER)
|
||||||
throw new AlfrescoRuntimeException("Wrong authentication setup for passthru authenticator (can only be used with LDAP/JAAS auth component)");
|
throw new AlfrescoRuntimeException("Wrong authentication setup for passthru authenticator (cannot be used with Alfresco users)");
|
||||||
|
|
||||||
// Load the passthru authenticator dynamically
|
// Load the passthru authenticator dynamically
|
||||||
|
|
||||||
|
@@ -3153,6 +3153,17 @@ public class NTProtocolHandler extends CoreProtocolHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the search is for an NTFS stream
|
||||||
|
|
||||||
|
if ( FileName.containsStreamName( srchPath))
|
||||||
|
{
|
||||||
|
// NTFS streams not supported
|
||||||
|
|
||||||
|
m_sess.sendErrorResponseSMB(SMBStatus.NTObjectNotFound, SMBStatus.SRVNonSpecificError,
|
||||||
|
SMBStatus.ErrSrv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Access the shared device disk interface
|
// Access the shared device disk interface
|
||||||
|
|
||||||
SearchContext ctx = null;
|
SearchContext ctx = null;
|
||||||
|
@@ -313,6 +313,16 @@ public class SMBSrvSession extends SrvSession implements Runnable
|
|||||||
m_vcircuits.removeCircuit(uid, this);
|
m_vcircuits.removeCircuit(uid, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the count of virtual circuits on this session
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public final int getVirtualCircuitCount()
|
||||||
|
{
|
||||||
|
return m_vcircuits != null ? m_vcircuits.getCircuitCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanup any resources owned by this session, close files, searches and
|
* Cleanup any resources owned by this session, close files, searches and
|
||||||
* change notification requests.
|
* change notification requests.
|
||||||
|
@@ -46,7 +46,9 @@ import org.alfresco.service.ServiceRegistry;
|
|||||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.lock.LockStatus;
|
import org.alfresco.service.cmr.lock.LockStatus;
|
||||||
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
@@ -298,6 +300,24 @@ public class Node implements Serializable, Scopeable
|
|||||||
{
|
{
|
||||||
if (name != null)
|
if (name != null)
|
||||||
{
|
{
|
||||||
|
QName typeQName = getType();
|
||||||
|
if ((services.getDictionaryService().isSubClass(typeQName, ContentModel.TYPE_FOLDER) &&
|
||||||
|
!services.getDictionaryService().isSubClass(typeQName, ContentModel.TYPE_SYSTEM_FOLDER)) ||
|
||||||
|
services.getDictionaryService().isSubClass(typeQName, ContentModel.TYPE_CONTENT))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.services.getFileFolderService().rename(this.nodeRef, name);
|
||||||
|
}
|
||||||
|
catch (FileExistsException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to rename node " + nodeRef + " to " + name, e);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to rename node " + nodeRef + " to " + name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.getProperties().put(ContentModel.PROP_NAME.toString(), name.toString());
|
this.getProperties().put(ContentModel.PROP_NAME.toString(), name.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,8 @@ import javax.transaction.UserTransaction;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.domain.ChildAssoc;
|
||||||
|
import org.alfresco.repo.domain.Node;
|
||||||
import org.alfresco.repo.domain.NodeStatus;
|
import org.alfresco.repo.domain.NodeStatus;
|
||||||
import org.alfresco.repo.node.BaseNodeServiceTest;
|
import org.alfresco.repo.node.BaseNodeServiceTest;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
@@ -353,4 +355,29 @@ public class DbNodeServiceImplTest extends BaseNodeServiceTest
|
|||||||
mlTextProperty,
|
mlTextProperty,
|
||||||
propertiesDirect.get(BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
|
propertiesDirect.get(BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDuplicatePrimaryParentHandling() throws Exception
|
||||||
|
{
|
||||||
|
Map<QName, ChildAssociationRef> assocRefs = buildNodeGraph();
|
||||||
|
// get the node to play with
|
||||||
|
ChildAssociationRef n1pn3Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n1_p_n3"));
|
||||||
|
ChildAssociationRef n6pn8Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n6_p_n8"));
|
||||||
|
final NodeRef n1Ref = n1pn3Ref.getParentRef();
|
||||||
|
final NodeRef n8Ref = n6pn8Ref.getChildRef();
|
||||||
|
|
||||||
|
// Add a make n1 a second primary parent of n8
|
||||||
|
Node n1 = nodeDaoService.getNode(n1Ref);
|
||||||
|
Node n8 = nodeDaoService.getNode(n8Ref);
|
||||||
|
ChildAssoc assoc = nodeDaoService.newChildAssoc(
|
||||||
|
n1,
|
||||||
|
n8,
|
||||||
|
true,
|
||||||
|
ContentModel.ASSOC_CONTAINS,
|
||||||
|
QName.createQName(NAMESPACE, "n1pn8"));
|
||||||
|
|
||||||
|
// Now get the node primary parent
|
||||||
|
nodeService.getPrimaryParent(n8Ref);
|
||||||
|
// Get it again
|
||||||
|
nodeService.getPrimaryParent(n8Ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -900,6 +900,15 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
getSession().flush();
|
getSession().flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<NodeRef> warnedDuplicateParents = new HashSet<NodeRef>(3);
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*
|
||||||
|
* This method includes a check for multiple primary parent associations.
|
||||||
|
* The check doesn't fail but will warn (once per instance) of the occurence of
|
||||||
|
* the error. It is up to the administrator to fix the issue at the moment, but
|
||||||
|
* the server will not stop working.
|
||||||
|
*/
|
||||||
public ChildAssoc getPrimaryParentAssoc(Node node)
|
public ChildAssoc getPrimaryParentAssoc(Node node)
|
||||||
{
|
{
|
||||||
// get the assocs pointing to the node
|
// get the assocs pointing to the node
|
||||||
@@ -914,12 +923,20 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
}
|
}
|
||||||
else if (primaryAssoc != null)
|
else if (primaryAssoc != null)
|
||||||
{
|
{
|
||||||
// we have more than one somehow
|
// We have found one already.
|
||||||
throw new DataIntegrityViolationException(
|
synchronized(warnedDuplicateParents)
|
||||||
"Multiple primary associations: \n" +
|
{
|
||||||
" child: " + node + "\n" +
|
NodeRef childNodeRef = node.getNodeRef();
|
||||||
" first primary assoc: " + primaryAssoc + "\n" +
|
boolean added = warnedDuplicateParents.add(childNodeRef);
|
||||||
" second primary assoc: " + assoc);
|
if (added)
|
||||||
|
{
|
||||||
|
logger.warn(
|
||||||
|
"Multiple primary associations: \n" +
|
||||||
|
" first primary assoc: " + primaryAssoc + "\n" +
|
||||||
|
" second primary assoc: " + assoc + "\n" +
|
||||||
|
"When running in a cluster, check that the caches are properly shared.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
primaryAssoc = assoc;
|
primaryAssoc = assoc;
|
||||||
// we keep looping to hunt out data integrity issues
|
// we keep looping to hunt out data integrity issues
|
||||||
@@ -938,9 +955,21 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
}
|
}
|
||||||
if (!rootNode.equals(node))
|
if (!rootNode.equals(node))
|
||||||
{
|
{
|
||||||
// it wasn't the root node
|
// Reload the node to ensure that it is properly initialized
|
||||||
throw new DataIntegrityViolationException("Non-root node has no primary parent: \n" +
|
getSession().refresh(node);
|
||||||
" child: " + node);
|
// Check if it has any parents yet.
|
||||||
|
if (node.getParentAssocs().size() == 0)
|
||||||
|
{
|
||||||
|
// It wasn't the root node and definitely has no parent
|
||||||
|
throw new DataIntegrityViolationException(
|
||||||
|
"Non-root node has no primary parent: \n" +
|
||||||
|
" child: " + node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Repeat this method with confidence
|
||||||
|
primaryAssoc = getPrimaryParentAssoc(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// done
|
// done
|
||||||
|
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.repo.node.index;
|
||||||
|
|
||||||
|
import org.alfresco.util.AbstractLifecycleBean;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
public class IndexRecoveryBootstrapBean extends AbstractLifecycleBean
|
||||||
|
{
|
||||||
|
protected final static Log log = LogFactory.getLog(IndexRecoveryBootstrapBean.class);
|
||||||
|
|
||||||
|
IndexRecovery indexRecoveryComponent;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBootstrap(ApplicationEvent event)
|
||||||
|
{
|
||||||
|
// reindex
|
||||||
|
log.info("Checking/Recovering indexes ...");
|
||||||
|
indexRecoveryComponent.reindex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onShutdown(ApplicationEvent event)
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexRecovery getIndexRecoveryComponent()
|
||||||
|
{
|
||||||
|
return indexRecoveryComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexRecoveryComponent(IndexRecovery indexRecoveryComponent)
|
||||||
|
{
|
||||||
|
this.indexRecoveryComponent = indexRecoveryComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user