KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > server > auth > passthru > PassthruAuthenticator


1 /*
2  * Copyright (C) 2006 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.passthru;
18
19 import java.util.Hashtable JavaDoc;
20
21 import javax.transaction.UserTransaction JavaDoc;
22
23 import org.alfresco.config.ConfigElement;
24 import org.alfresco.error.AlfrescoRuntimeException;
25 import org.alfresco.filesys.server.SessionListener;
26 import org.alfresco.filesys.server.SrvSession;
27 import org.alfresco.filesys.server.auth.ClientInfo;
28 import org.alfresco.filesys.server.auth.SrvAuthenticator;
29 import org.alfresco.filesys.server.auth.UserAccount;
30 import org.alfresco.filesys.server.config.InvalidConfigurationException;
31 import org.alfresco.filesys.server.config.ServerConfiguration;
32 import org.alfresco.filesys.server.core.SharedDevice;
33 import org.alfresco.filesys.smb.server.SMBServer;
34 import org.alfresco.filesys.smb.server.SMBSrvSession;
35 import org.alfresco.filesys.util.HexDump;
36 import org.alfresco.model.ContentModel;
37 import org.alfresco.service.cmr.repository.NodeRef;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 /**
42  * Passthru Authenticator Class
43  * <p>
44  * Authenticate users accessing the CIFS server by validating the user against a domain controller
45  * or other server on the network.
46  *
47  * @author GKSpencer
48  */

49 public class PassthruAuthenticator extends SrvAuthenticator implements SessionListener
50 {
51     // Debug logging
52

53     private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.auth");
54
55     // Constants
56

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

61     // Passthru servers used to authenticate users
62

63     private PassthruServers m_passthruServers;
64
65     // SMB server
66

67     private SMBServer m_server;
68
69     // Sessions that are currently in the negotiate/session setup state
70

71     private Hashtable JavaDoc<String JavaDoc, PassthruDetails> m_sessions;
72
73     /**
74      * Passthru Authenticator Constructor
75      * <p>
76      * Default to user mode security with encrypted password support.
77      */

78     public PassthruAuthenticator()
79     {
80         setAccessMode(SrvAuthenticator.USER_MODE);
81         setEncryptedPasswords(true);
82
83         // Allocate the session table
84

85         m_sessions = new Hashtable JavaDoc<String JavaDoc, PassthruDetails>();
86     }
87
88     /**
89      * Authenticate the connection to a particular share, called when the SMB server is in share
90      * security mode
91      *
92      * @param client ClientInfo
93      * @param share SharedDevice
94      * @param sharePwd String
95      * @param sess SrvSession
96      * @return int
97      */

98     public int authenticateShareConnect(ClientInfo client, SharedDevice share, String JavaDoc sharePwd, SrvSession sess)
99     {
100         return SrvAuthenticator.Writeable;
101     }
102
103     /**
104      * Authenticate a session setup by a user
105      *
106      * @param client ClientInfo
107      * @param sess SrvSession
108      * @param alg int
109      * @return int
110      */

111     public int authenticateUser(ClientInfo client, SrvSession sess, int alg)
112     {
113         // Check if this is an SMB/CIFS null session logon.
114
//
115
// The null session will only be allowed to connect to the IPC$ named pipe share.
116

117         if (client.isNullSession() && sess instanceof SMBSrvSession)
118         {
119             // Debug
120

121             if ( logger.isDebugEnabled())
122                 logger.debug("Null CIFS logon allowed");
123
124             return SrvAuthenticator.AUTH_ALLOW;
125         }
126
127         // Check if the client is already authenticated, and it is not a null logon
128

129         if ( client.getAuthenticationToken() != null && client.getLogonType() != ClientInfo.LogonNull)
130         {
131             // Use the existing authentication token
132

133             m_authComponent.setCurrentUser(client.getUserName());
134
135             // Debug
136

137             if ( logger.isDebugEnabled())
138                 logger.debug("Re-using existing authentication token");
139             
140             // Return the authentication status
141

142             return client.getLogonType() != ClientInfo.LogonGuest ? AUTH_ALLOW : AUTH_GUEST;
143         }
144         
145         // Check if this is a guest logon
146

147         int authSts = AUTH_DISALLOW;
148         
149         if ( client.isGuest() || client.getUserName().equalsIgnoreCase(getGuestUserName()))
150         {
151             // Check if guest logons are allowed
152

153             if ( allowGuest() == false)
154                 return AUTH_DISALLOW;
155             
156             // Get a guest authentication token
157

158             doGuestLogon( client, sess);
159             
160             // Indicate logged on as guest
161

162             authSts = AUTH_GUEST;
163             
164             // DEBUG
165

166             if ( logger.isDebugEnabled())
167                 logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts));
168             
169             // Return the guest status
170

171             return authSts;
172         }
173
174         // Find the active authentication session details for the server session
175

176         PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
177
178         if (passDetails != null)
179         {
180
181             try
182             {
183
184                 // Authenticate the user by passing the hashed password to the authentication server
185
// using the session that has already been setup.
186

187                 AuthenticateSession authSess = passDetails.getAuthenticateSession();
188                 authSess.doSessionSetup(client.getUserName(), client.getANSIPassword(), client.getPassword());
189
190                 // Check if the user has been logged on as a guest
191

192                 if (authSess.isGuest())
193                 {
194
195                     // Check if the local server allows guest access
196

197                     if (allowGuest() == true)
198                     {
199                         // Get a guest authentication token
200

201                         doGuestLogon( client, sess);
202                         
203                         // Allow the user access as a guest
204

205                         authSts = SrvAuthenticator.AUTH_GUEST;
206
207                         // Debug
208

209                         if (logger.isDebugEnabled())
210                             logger.debug("Passthru authenticate user=" + client.getUserName() + ", GUEST");
211                     }
212                 }
213                 else
214                 {
215                     // Wrap the service calls in a transaction
216

217                     UserTransaction JavaDoc tx = m_transactionService.getUserTransaction( true);
218                     
219                     try
220                     {
221                         // Start the transaction
222

223                         tx.begin();
224                         
225                         // Map the passthru username to an Alfresco person
226

227                         String JavaDoc username = client.getUserName();
228                         NodeRef userNode = m_personService.getPerson( username);
229                         
230                         if ( userNode != null)
231                         {
232                             // Get the person name and use that as the current user to line up with permission checks
233

234                             String JavaDoc personName = (String JavaDoc) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
235                             m_authComponent.setCurrentUser(personName);
236                             
237                             // DEBUG
238

239                             if ( logger.isDebugEnabled())
240                                 logger.debug("Setting current user using person " + personName + " (username " + username + ")");
241                         }
242                         else
243                         {
244                             // Set using the user name, lowercase the name if the person service is case insensitive
245

246                             if ( m_personService.getUserNamesAreCaseSensitive() == false)
247                                 username = username.toLowerCase();
248                             m_authComponent.setCurrentUser( username);
249                             
250                             // DEBUG
251

252                             if ( logger.isDebugEnabled())
253                                 logger.debug("Setting current user using username " + username);
254                         }
255
256                         // Allow the user full access to the server
257

258                         authSts = SrvAuthenticator.AUTH_ALLOW;
259
260                         // Debug
261

262                         if (logger.isDebugEnabled())
263                             logger.debug("Passthru authenticate user=" + client.getUserName() + ", FULL");
264                     }
265                     finally
266                     {
267                         // Commit the transaction
268

269                         if ( tx != null)
270                         {
271                             try {
272                                 tx.commit();
273                             }
274                             catch (Exception JavaDoc ex)
275                             {
276                                 // Sink it
277
}
278                         }
279                     }
280                 }
281             }
282             catch (Exception JavaDoc ex)
283             {
284
285                 // Debug
286

287                 logger.error(ex.getMessage());
288             }
289
290             // Keep the authentication session if the user session is an SMB session, else close the
291
// session now
292

293             if ((sess instanceof SMBSrvSession) == false)
294             {
295
296                 // Remove the passthru session from the active list
297

298                 m_sessions.remove(sess.getUniqueId());
299
300                 // Close the passthru authentication session
301

302                 try
303                 {
304
305                     // Close the authentication session
306

307                     AuthenticateSession authSess = passDetails.getAuthenticateSession();
308                     authSess.CloseSession();
309
310                     // DEBUG
311

312                     if (logger.isDebugEnabled())
313                         logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
314                 }
315                 catch (Exception JavaDoc ex)
316                 {
317
318                     // Debug
319

320                     logger.error("Passthru error closing session (auth user)", ex);
321                 }
322             }
323         }
324         else
325         {
326
327             // DEBUG
328

329             if (logger.isDebugEnabled())
330                 logger.debug(" No PassthruDetails for " + sess.getUniqueId());
331         }
332
333         // Return the authentication status
334

335         return authSts;
336     }
337
338     /**
339      * Get user account details for the specified user
340      *
341      * @param user String
342      * @return UserAccount
343      */

344     public UserAccount getUserDetails(String JavaDoc user)
345     {
346
347         // No user details to return
348

349         return null;
350     }
351
352     /**
353      * Get a challenge key for a new session
354      *
355      * @param sess SrvSession
356      * @return byte[]
357      */

358     public byte[] getChallengeKey(SrvSession sess)
359     {
360
361         // Check for an SMB session
362

363         byte[] chKey = null;
364
365         // Check if the client is already authenticated, and it is not a null logon
366

367         if ( sess.hasClientInformation() && sess.getClientInformation().getAuthenticationToken() != null &&
368                 sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
369         {
370             // DEBUG
371

372             if ( logger.isDebugEnabled())
373                 logger.debug("Re-using existing challenge, already authenticated");
374
375             // Return the previous challenge, user is already authenticated
376

377             return sess.getChallengeKey();
378         }
379         else if (sess instanceof SMBSrvSession)
380         {
381
382             // Check if the SMB server listener has been initialized
383

384             if (m_server == null)
385             {
386
387                 // Initialize the SMB server session listener so we receive callbacks when sessions
388
// are opened/closed on the SMB server
389

390                 SMBSrvSession smbSess = (SMBSrvSession) sess;
391                 m_server = smbSess.getSMBServer();
392
393                 m_server.addSessionListener(this);
394             }
395         }
396
397         try
398         {
399
400             // Open a connection to the authentication server
401

402             AuthenticateSession authSess = m_passthruServers.openSession();
403             if (authSess != null)
404             {
405
406                 // Create an entry in the active sessions table for the new session
407

408                 PassthruDetails passDetails = new PassthruDetails(sess, authSess);
409                 m_sessions.put(sess.getUniqueId(), passDetails);
410
411                 // Use the challenge key returned from the authentication server
412

413                 chKey = authSess.getEncryptionKey();
414
415                 // DEBUG
416

417                 if (logger.isDebugEnabled())
418                     logger.debug("Passthru sessId=" + authSess.getSessionId() + ", negotiate key=["
419                             + HexDump.hexString(chKey) + "]");
420             }
421         }
422         catch (Exception JavaDoc ex)
423         {
424
425             // Debug
426

427             logger.error("Passthru error getting challenge", ex);
428         }
429
430         // Return the challenge key
431

432         return chKey;
433     }
434
435     /**
436      * Initialzie the authenticator
437      *
438      * @param config ServerConfiguration
439      * @param params ConfigElement
440      * @exception InvalidConfigurationException
441      */

442     public void initialize(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException
443     {
444
445         // Call the base class
446

447         super.initialize(config, params);
448
449         // Create the passthru authentication server list
450

451         m_passthruServers = new PassthruServers();
452         
453         // Check if the session timeout has been specified
454

455         ConfigElement sessTmoElem = params.getChild("Timeout");
456         if (sessTmoElem != null)
457         {
458
459             try
460             {
461
462                 // Validate the session timeout value
463

464                 int sessTmo = Integer.parseInt(sessTmoElem.getValue());
465                 
466                 // Range check the timeout
467

468                 if ( sessTmo < MinSessionTmo || sessTmo > MaxSessionTmo)
469                     throw new InvalidConfigurationException("Invalid session timeout, valid range is " +
470                                                             MinSessionTmo + " to " + MaxSessionTmo);
471                 
472                 // Set the session timeout for connecting to an authentication server
473

474                 m_passthruServers.setConnectionTimeout( sessTmo);
475             }
476             catch (NumberFormatException JavaDoc ex)
477             {
478                 throw new InvalidConfigurationException("Invalid timeout value specified");
479             }
480         }
481
482         // Check if the local server should be used
483

484         String JavaDoc srvList = null;
485
486         if (params.getChild("LocalServer") != null)
487         {
488
489             // Get the local server name, trim the domain name
490

491             srvList = config.getLocalServerName(true);
492             if(srvList == null)
493                 throw new AlfrescoRuntimeException("Passthru authenticator failed to get local server name");
494         }
495
496         // Check if a server name has been specified
497

498         ConfigElement srvNamesElem = params.getChild("Server");
499
500         if (srvNamesElem != null && srvNamesElem.getValue().length() > 0)
501         {
502
503             // Check if the server name was already set
504

505             if (srvList != null)
506                 throw new AlfrescoRuntimeException("Set passthru server via local server or specify name");
507
508             // Get the passthru authenticator server name
509

510             srvList = srvNamesElem.getValue();
511         }
512
513         // If the passthru server name has been set initialize the passthru connection
514

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

519             m_passthruServers.setServerList(srvList);
520         }
521         else
522         {
523
524             // Get the domain/workgroup name
525

526             String JavaDoc domainName = null;
527             
528             // Check if the local domain/workgroup should be used
529

530             if (params.getChild("LocalDomain") != null)
531             {
532                 // Get the local domain/workgroup name
533

534                 domainName = config.getLocalDomainName();
535             }
536             
537             // Check if a domain name has been specified
538

539             ConfigElement domNameElem = params.getChild("Domain");
540
541             if (domNameElem != null && domNameElem.getValue().length() > 0)
542             {
543
544                 // Check if the authentication server has already been set, ie. server name was also specified
545

546                 if (srvList != null)
547                     throw new AlfrescoRuntimeException("Specify server or domain name for passthru authentication");
548
549                 domainName = domNameElem.getValue();
550             }
551             
552             // If the domain name has been set initialize the passthru connection
553

554             if (domainName != null)
555             {
556                 // Initialize using the domain
557

558                 m_passthruServers.setDomain(domainName);
559             }
560         }
561
562         // Check if we have an authentication server
563

564         if (m_passthruServers.getTotalServerCount() == 0)
565             throw new AlfrescoRuntimeException("No valid authentication servers found for passthru");
566     }
567
568     /**
569      * Close the authenticator, perform cleanup
570      */

571     public void closeAuthenticator()
572     {
573         // Close the passthru authentication server list
574

575         if ( m_passthruServers != null)
576             m_passthruServers.shutdown();
577     }
578     
579     /**
580      * SMB server session closed notification
581      *
582      * @param sess SrvSession
583      */

584     public void sessionClosed(SrvSession sess)
585     {
586
587         // Check if there is an active session to the authentication server for this local
588
// session
589

590         PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
591
592         if (passDetails != null)
593         {
594
595             // Remove the passthru session from the active list
596

597             m_sessions.remove(sess.getUniqueId());
598
599             // Close the passthru authentication session
600

601             try
602             {
603
604                 // Close the authentication session
605

606                 AuthenticateSession authSess = passDetails.getAuthenticateSession();
607                 authSess.CloseSession();
608
609                 // DEBUG
610

611                 if (logger.isDebugEnabled())
612                     logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
613             }
614             catch (Exception JavaDoc ex)
615             {
616
617                 // Debug
618

619                 logger.error("Passthru error closing session (closed)", ex);
620             }
621         }
622     }
623
624     /**
625      * SMB server session created notification
626      *
627      * @param sess SrvSession
628      */

629     public void sessionCreated(SrvSession sess)
630     {
631     }
632
633     /**
634      * User successfully logged on notification
635      *
636      * @param sess SrvSession
637      */

638     public void sessionLoggedOn(SrvSession sess)
639     {
640
641         // Check if the client information has an empty user name, if so then do not close the
642
// authentication
643
// session
644

645         if (sess.hasClientInformation() && sess.getClientInformation().getUserName() != null
646                 && sess.getClientInformation().getUserName().length() > 0)
647         {
648
649             // Check if there is an active session to the authentication server for this local
650
// session
651

652             PassthruDetails passDetails = m_sessions.get(sess.getUniqueId());
653
654             if (passDetails != null)
655             {
656
657                 // Remove the passthru session from the active list
658

659                 m_sessions.remove(sess.getUniqueId());
660
661                 // Close the passthru authentication session
662

663                 try
664                 {
665
666                     // Close the authentication session
667

668                     AuthenticateSession authSess = passDetails.getAuthenticateSession();
669                     authSess.CloseSession();
670
671                     // DEBUG
672

673                     if (logger.isDebugEnabled())
674                         logger.debug("Closed auth session, sessId=" + authSess.getSessionId());
675                 }
676                 catch (Exception JavaDoc ex)
677                 {
678
679                     // Debug
680

681                     logger.error("Passthru error closing session (logon)", ex);
682                 }
683             }
684         }
685     }
686 }
687
Popular Tags