KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > server > auth > AlfrescoAuthenticator


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.server.auth;
18
19 import java.security.NoSuchAlgorithmException JavaDoc;
20
21 import org.alfresco.filesys.server.SrvSession;
22 import org.alfresco.filesys.smb.server.SMBSrvSession;
23 import org.alfresco.filesys.util.DataPacker;
24 import org.alfresco.repo.security.authentication.NTLMMode;
25
26 /**
27  * Alfresco Authenticator Class
28  *
29  * <p>The Alfresco authenticator implementation enables user level security mode using the Alfresco authentication
30  * component.
31  *
32  * <p>Note: Switching off encrypted password support will cause later NT4 service pack releases and
33  * Win2000 to refuse to connect to the server without a registry update on the client.
34  *
35  * @author GKSpencer
36  */

37 public class AlfrescoAuthenticator extends SrvAuthenticator
38 {
39     /**
40      * Default Constructor
41      *
42      * <p>Default to user mode security with encrypted password support.
43      */

44     public AlfrescoAuthenticator()
45     {
46         setAccessMode(SrvAuthenticator.USER_MODE);
47         setEncryptedPasswords(true);
48     }
49
50     /**
51      * Validate that the authentication component supports the required mode
52      *
53      * @return boolean
54      */

55     protected boolean validateAuthenticationMode()
56     {
57         // Make sure the authentication component supports MD4 hashed passwords or passthru mode
58

59         if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
60                 m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
61             return false;
62         return true;
63     }
64     
65     /**
66      * Authenticate a user
67      *
68      * @param client Client information
69      * @param sess Server session
70      * @param alg Encryption algorithm
71      */

72     public int authenticateUser(ClientInfo client, SrvSession sess, int alg)
73     {
74         // Check if this is an SMB/CIFS null session logon.
75
//
76
// The null session will only be allowed to connect to the IPC$ named pipe share.
77

78         if (client.isNullSession() && sess instanceof SMBSrvSession)
79         {
80             // Debug
81

82             if ( logger.isDebugEnabled())
83                 logger.debug("Null CIFS logon allowed");
84
85             return SrvAuthenticator.AUTH_ALLOW;
86         }
87
88         // Check if the client is already authenticated, and it is not a null logon
89

90         if ( client.getAuthenticationToken() != null && client.getLogonType() != ClientInfo.LogonNull)
91         {
92             // Use the existing authentication token
93

94             if ( client.isGuest())
95                 m_authComponent.setGuestUserAsCurrentUser();
96             else
97                 m_authComponent.setCurrentUser(client.getUserName());
98
99             // Debug
100

101             if ( logger.isDebugEnabled())
102                 logger.debug("Re-using existing authentication token");
103             
104             // Return the authentication status
105

106             return client.getLogonType() != ClientInfo.LogonGuest ? AUTH_ALLOW : AUTH_GUEST;
107         }
108         
109         // Check if this is a guest logon
110

111         int authSts = AUTH_DISALLOW;
112         
113         if ( client.isGuest() || client.getUserName().equalsIgnoreCase(GUEST_USERNAME))
114         {
115             // Check if guest logons are allowed
116

117             if ( allowGuest() == false)
118                 return AUTH_DISALLOW;
119             
120             // Get a guest authentication token
121

122             doGuestLogon( client, sess);
123             
124             // Indicate logged on as guest
125

126             authSts = AUTH_GUEST;
127             
128             // DEBUG
129

130             if ( logger.isDebugEnabled())
131                 logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts));
132             
133             // Return the guest status
134

135             return authSts;
136         }
137         
138         // Check if MD4 or passthru mode is configured
139

140         else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
141         {
142             // Perform local MD4 password check
143

144             authSts = doMD4UserAuthentication(client, sess, alg);
145         }
146
147         // Check if the logon status indicates a guest logon
148

149         if ( authSts == AUTH_GUEST)
150         {
151             // Only allow the guest logon if user mapping is enabled
152

153             if ( mapUnknownUserToGuest())
154             {
155                 // Logon as guest, setup the security context
156

157                 doGuestLogon( client, sess);
158             }
159             else
160             {
161                 // Do not allow the guest logon
162

163                 authSts = AUTH_DISALLOW;
164             }
165         }
166         
167         // DEBUG
168

169         if ( logger.isDebugEnabled())
170             logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts) +
171                     " via " + (m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER ? "MD4" : "Passthru"));
172                     
173         // Return the authentication status
174

175         return authSts;
176     }
177
178     /**
179      * Generate a challenge key
180      *
181      * @param sess SrvSession
182      * @return byte[]
183      */

184     public byte[] getChallengeKey(SrvSession sess)
185     {
186         // In MD4 mode we generate the challenge locally
187

188         byte[] key = null;
189         
190         // Check if the client is already authenticated, and it is not a null logon
191

192         if ( sess.hasClientInformation() && sess.getClientInformation().getAuthenticationToken() != null &&
193                 sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
194         {
195             // Return the previous challenge, user is already authenticated
196

197             key = sess.getChallengeKey();
198             
199             // DEBUG
200

201             if ( logger.isDebugEnabled())
202                 logger.debug("Re-using existing challenge, already authenticated");
203         }
204         else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
205         {
206             // Generate a new challenge key, pack the key and return
207

208             key = new byte[8];
209     
210             DataPacker.putIntelLong(m_random.nextLong(), key, 0);
211         }
212
213         // Return the challenge
214

215         return key;
216     }
217
218     /**
219      * Perform MD4 user authentication
220      *
221      * @param client Client information
222      * @param sess Server session
223      * @param alg Encryption algorithm
224      * @return int
225      */

226     private final int doMD4UserAuthentication(ClientInfo client, SrvSession sess, int alg)
227     {
228         // Get the stored MD4 hashed password for the user, or null if the user does not exist
229

230         String JavaDoc md4hash = m_authComponent.getMD4HashedPassword(client.getUserName());
231         
232         if ( md4hash != null)
233         {
234             // Check if the client has supplied an NTLM hashed password, if not then do not allow access
235

236             if ( client.getPassword() == null)
237                 return SrvAuthenticator.AUTH_BADPASSWORD;
238             
239             try
240             {
241                 // Generate the local encrypted password using the challenge that was sent to the client
242

243                 byte[] p21 = new byte[21];
244                 byte[] md4byts = m_md4Encoder.decodeHash(md4hash);
245                 System.arraycopy(md4byts, 0, p21, 0, 16);
246                 
247                 // Generate the local hash of the password using the same challenge
248

249                 byte[] localHash = getEncryptor().doNTLM1Encryption(p21, sess.getChallengeKey());
250                 
251                 // Validate the password
252

253                 byte[] clientHash = client.getPassword();
254
255                 if ( clientHash == null || clientHash.length != localHash.length)
256                     return SrvAuthenticator.AUTH_BADPASSWORD;
257                 
258                 for ( int i = 0; i < clientHash.length; i++)
259                 {
260                     if ( clientHash[i] != localHash[i])
261                         return SrvAuthenticator.AUTH_BADPASSWORD;
262                 }
263                 
264                 // Set the current user to be authenticated, save the authentication token
265

266                 client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName()));
267                 
268                 // Get the users home folder node, if available
269

270                 getHomeFolderForUser( client);
271                 
272                 // Passwords match, grant access
273

274                 return SrvAuthenticator.AUTH_ALLOW;
275             }
276             catch (NoSuchAlgorithmException JavaDoc ex)
277             {
278             }
279             
280             // Error during password check, do not allow access
281

282             return SrvAuthenticator.AUTH_DISALLOW;
283         }
284
285         // Check if this is an SMB/CIFS null session logon.
286
//
287
// The null session will only be allowed to connect to the IPC$ named pipe share.
288

289         if (client.isNullSession() && sess instanceof SMBSrvSession)
290             return SrvAuthenticator.AUTH_ALLOW;
291         
292         // User does not exist, check if guest access is allowed
293

294         return allowGuest() ? SrvAuthenticator.AUTH_GUEST : SrvAuthenticator.AUTH_DISALLOW;
295     }
296 }
Popular Tags