KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > app > servlet > NTLMAuthenticationFilter


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.web.app.servlet;
18
19 import java.io.IOException JavaDoc;
20 import java.net.InetAddress JavaDoc;
21 import java.net.UnknownHostException JavaDoc;
22 import java.security.NoSuchAlgorithmException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Locale JavaDoc;
26 import java.util.Random JavaDoc;
27
28 import javax.servlet.Filter JavaDoc;
29 import javax.servlet.FilterChain JavaDoc;
30 import javax.servlet.FilterConfig JavaDoc;
31 import javax.servlet.ServletContext JavaDoc;
32 import javax.servlet.ServletException JavaDoc;
33 import javax.servlet.ServletRequest JavaDoc;
34 import javax.servlet.ServletResponse JavaDoc;
35 import javax.servlet.http.HttpServletRequest JavaDoc;
36 import javax.servlet.http.HttpServletResponse JavaDoc;
37 import javax.servlet.http.HttpSession JavaDoc;
38 import javax.transaction.UserTransaction JavaDoc;
39
40 import net.sf.acegisecurity.BadCredentialsException;
41
42 import org.alfresco.config.ConfigService;
43 import org.alfresco.filesys.server.auth.PasswordEncryptor;
44 import org.alfresco.filesys.server.auth.ntlm.NTLM;
45 import org.alfresco.filesys.server.auth.ntlm.NTLMLogonDetails;
46 import org.alfresco.filesys.server.auth.ntlm.NTLMMessage;
47 import org.alfresco.filesys.server.auth.ntlm.TargetInfo;
48 import org.alfresco.filesys.server.auth.ntlm.Type1NTLMMessage;
49 import org.alfresco.filesys.server.auth.ntlm.Type2NTLMMessage;
50 import org.alfresco.filesys.server.auth.ntlm.Type3NTLMMessage;
51 import org.alfresco.filesys.server.config.ServerConfiguration;
52 import org.alfresco.filesys.util.DataPacker;
53 import org.alfresco.i18n.I18NUtil;
54 import org.alfresco.model.ContentModel;
55 import org.alfresco.repo.security.authentication.AuthenticationComponent;
56 import org.alfresco.repo.security.authentication.AuthenticationException;
57 import org.alfresco.repo.security.authentication.MD4PasswordEncoder;
58 import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl;
59 import org.alfresco.repo.security.authentication.NTLMMode;
60 import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
61 import org.alfresco.service.ServiceRegistry;
62 import org.alfresco.service.cmr.repository.NodeRef;
63 import org.alfresco.service.cmr.repository.NodeService;
64 import org.alfresco.service.cmr.security.AuthenticationService;
65 import org.alfresco.service.cmr.security.PersonService;
66 import org.alfresco.service.transaction.TransactionService;
67 import org.alfresco.web.app.Application;
68 import org.alfresco.web.bean.LoginBean;
69 import org.alfresco.web.bean.repository.User;
70 import org.alfresco.web.config.LanguagesConfigElement;
71 import org.apache.commons.codec.binary.Base64;
72 import org.apache.commons.logging.Log;
73 import org.apache.commons.logging.LogFactory;
74 import org.springframework.web.context.WebApplicationContext;
75 import org.springframework.web.context.support.WebApplicationContextUtils;
76
77 /**
78  * NTLM Authentication Filter Class
79  *
80  * @author GKSpencer
81  */

82 public class NTLMAuthenticationFilter extends AbstractAuthenticationFilter implements Filter JavaDoc
83 {
84     // NTLM authentication session object names
85

86     public static final String JavaDoc NTLM_AUTH_SESSION = "_alfNTLMAuthSess";
87     public static final String JavaDoc NTLM_AUTH_DETAILS = "_alfNTLMDetails";
88
89     // Locale object stored in the session
90

91     private static final String JavaDoc LOCALE = "locale";
92     public static final String JavaDoc MESSAGE_BUNDLE = "alfresco.messages.webclient";
93     
94     // NTLM flags mask, used to mask out features that are not supported
95

96     private static final int NTLM_FLAGS = NTLM.Flag56Bit + NTLM.FlagLanManKey + NTLM.FlagNegotiateNTLM +
97                                           NTLM.FlagNegotiateOEM + NTLM.FlagNegotiateUnicode;
98     
99     // Debug logging
100

101     private static Log logger = LogFactory.getLog(NTLMAuthenticationFilter.class);
102     
103     // Servlet context, required to get authentication service
104

105     private ServletContext JavaDoc m_context;
106     
107     // File server configuration
108

109     private ServerConfiguration m_srvConfig;
110     
111     // Various services required by NTLM authenticator
112

113     private AuthenticationService m_authService;
114     private AuthenticationComponent m_authComponent;
115     private PersonService m_personService;
116     private NodeService m_nodeService;
117     private TransactionService m_transactionService;
118     private ConfigService m_configService;
119     
120     // Password encryptor
121

122     private PasswordEncryptor m_encryptor = new PasswordEncryptor();
123     
124     // Allow guest access
125

126     private boolean m_allowGuest;
127     
128     // Login page address
129

130     private String JavaDoc m_loginPage;
131
132     // Random number generator used to generate challenge keys
133

134     private Random JavaDoc m_random = new Random JavaDoc(System.currentTimeMillis());
135     
136     // MD4 hash decoder
137

138     private MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl();
139     
140     // Local server name, from either the file servers config or DNS host name
141

142     private String JavaDoc m_srvName;
143     
144     // List of available locales (from the web-client configuration)
145

146     private List JavaDoc<String JavaDoc> m_languages;
147     
148     /**
149      * Initialize the filter
150      *
151      * @param args FilterConfig
152      * @exception ServletException
153      */

154     public void init(FilterConfig JavaDoc args) throws ServletException JavaDoc
155     {
156         // Save the servlet context, needed to get hold of the authentication service
157

158         m_context = args.getServletContext();
159
160         // Setup the authentication context
161

162         WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
163         
164         ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
165         m_nodeService = serviceRegistry.getNodeService();
166         m_transactionService = serviceRegistry.getTransactionService();
167
168         m_authService = (AuthenticationService) ctx.getBean("authenticationService");
169         m_authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
170         m_personService = (PersonService) ctx.getBean("personService");
171         m_configService = (ConfigService) ctx.getBean("webClientConfigService");
172         
173         m_srvConfig = (ServerConfiguration) ctx.getBean(ServerConfiguration.SERVER_CONFIGURATION);
174         
175         // Check that the authentication component supports the required mode
176

177         if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
178                 m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
179         {
180             throw new ServletException JavaDoc("Required authentication mode not available");
181         }
182         
183         // Get the local server name, try the file server config first
184

185         if ( m_srvConfig != null)
186         {
187             m_srvName = m_srvConfig.getServerName();
188             
189             if ( m_srvName == null)
190             {
191                 // CIFS server may not be running so the local server name has not been set, generate
192
// a server name
193

194                 m_srvName = m_srvConfig.getLocalServerName(true) + "_A";
195             }
196         }
197         else
198         {
199             // Get the host name
200

201             try
202             {
203                 // Get the local host name
204

205                 m_srvName = InetAddress.getLocalHost().getHostName();
206                 
207                 // Strip any domain name
208

209                 int pos = m_srvName.indexOf(".");
210                 if ( pos != -1)
211                     m_srvName = m_srvName.substring(0, pos - 1);
212             }
213             catch (UnknownHostException JavaDoc ex)
214             {
215                 // Log the error
216

217                 if ( logger.isErrorEnabled())
218                     logger.error("NTLM filter, error getting local host name", ex);
219             }
220             
221         }
222         
223         // Check if the server name is valid
224

225         if ( m_srvName == null || m_srvName.length() == 0)
226             throw new ServletException JavaDoc("Failed to get local server name");
227         
228         // Check if guest access is to be allowed
229

230         String JavaDoc guestAccess = args.getInitParameter("AllowGuest");
231         if ( guestAccess != null)
232         {
233             m_allowGuest = Boolean.parseBoolean(guestAccess);
234             
235             // Debug
236

237             if ( logger.isDebugEnabled() && m_allowGuest)
238                 logger.debug("NTLM filter guest access allowed");
239         }
240
241         // Get a list of the available locales
242

243         LanguagesConfigElement config = (LanguagesConfigElement) m_configService.
244               getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
245   
246         m_languages = config.getLanguages();
247     }
248
249     /**
250      * Run the filter
251      *
252      * @param sreq ServletRequest
253      * @param sresp ServletResponse
254      * @param chain FilterChain
255      * @exception IOException
256      * @exception ServletException
257      */

258     public void doFilter(ServletRequest JavaDoc sreq, ServletResponse JavaDoc sresp, FilterChain JavaDoc chain) throws IOException JavaDoc,
259             ServletException JavaDoc
260     {
261         // Get the HTTP request/response/session
262

263         HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc) sreq;
264         HttpServletResponse JavaDoc resp = (HttpServletResponse JavaDoc) sresp;
265         
266         HttpSession JavaDoc httpSess = req.getSession(true);
267
268         // Check if there is an authorization header with an NTLM security blob
269

270         String JavaDoc authHdr = req.getHeader("Authorization");
271         boolean reqAuth = false;
272         
273         if ( authHdr != null && authHdr.startsWith("NTLM"))
274             reqAuth = true;
275         
276         // Check if the user is already authenticated
277

278         User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
279         
280         if ( user != null && reqAuth == false)
281         {
282             try
283             {
284                 // Debug
285

286                 if ( logger.isDebugEnabled())
287                     logger.debug("User " + user.getUserName() + " validate ticket");
288                 
289                 // Validate the user ticket
290

291                 m_authService.validate( user.getTicket());
292                 reqAuth = false;
293                 
294                 // Set the current locale
295

296                 I18NUtil.setLocale(Application.getLanguage(httpSess));
297             }
298             catch (AuthenticationException ex)
299             {
300                 if ( logger.isErrorEnabled())
301                     logger.error("Failed to validate user " + user.getUserName(), ex);
302                 
303                 reqAuth = true;
304             }
305         }
306
307         // If the user has been validated and we do not require re-authentication then continue to
308
// the next filter
309

310         if ( reqAuth == false && user != null)
311         {
312             // Debug
313

314             if ( logger.isDebugEnabled())
315                 logger.debug("Authentication not required, chaining ...");
316             
317             // Chain to the next filter
318

319             chain.doFilter(sreq, sresp);
320             return;
321         }
322
323         // Check if the login page is being accessed, do not intercept the login page
324

325         if ( req.getRequestURI().endsWith(getLoginPage()) == true)
326         {
327             // Debug
328

329             if ( logger.isDebugEnabled())
330                 logger.debug("Login page requested, chaining ...");
331             
332             // Chain to the next filter
333

334             chain.doFilter( sreq, sresp);
335             return;
336         }
337         
338         // Check if the browser is Opera, if so then display the login page as Opera does not
339
// support NTLM and displays an error page if a request to use NTLM is sent to it
340

341         String JavaDoc userAgent = req.getHeader("user-agent");
342         
343         if ( userAgent != null && userAgent.indexOf("Opera ") != -1)
344         {
345             // Debug
346

347             if ( logger.isDebugEnabled())
348                 logger.debug("Opera detected, redirecting to login page");
349
350             // Redirect to the login page
351

352             resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
353             return;
354         }
355         
356         // Check the authorization header
357

358         if ( authHdr == null) {
359
360             // Debug
361

362             if ( logger.isDebugEnabled())
363                 logger.debug("New NTLM auth request from " + req.getRemoteHost() + " (" +
364                         req.getRemoteAddr() + ":" + req.getRemotePort() + ")");
365             
366             // Send back a request for NTLM authentication
367

368             resp.setHeader("WWW-Authenticate", "NTLM");
369             resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
370             
371             resp.flushBuffer();
372         }
373         else {
374             
375             // Get the existing NTLM details
376

377             NTLMLogonDetails ntlmDetails = null;
378             
379             if ( httpSess != null)
380             {
381                 ntlmDetails = (NTLMLogonDetails) httpSess.getAttribute(NTLM_AUTH_DETAILS);
382             }
383                 
384             // Decode the received NTLM blob and validate
385

386             final byte[] ntlmByts = Base64.decodeBase64( authHdr.substring(5).getBytes());
387             int ntlmTyp = NTLMMessage.isNTLMType(ntlmByts);
388          
389             if ( ntlmTyp == NTLM.Type1)
390             {
391                 // Process the type 1 NTLM message
392

393                 Type1NTLMMessage type1Msg = new Type1NTLMMessage(ntlmByts);
394                 processType1(type1Msg, req, resp, httpSess);
395             }
396             else if ( ntlmTyp == NTLM.Type3)
397             {
398                 // Process the type 3 NTLM message
399

400                 Type3NTLMMessage type3Msg = new Type3NTLMMessage(ntlmByts);
401                 processType3(type3Msg, req, resp, httpSess, chain);
402             }
403             else
404             {
405                 // Debug
406

407                 if ( logger.isDebugEnabled())
408                     logger.debug("NTLM not handled, redirecting to login page");
409                 
410                 // Redirect to the login page
411

412                 resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
413             }
414         }
415     }
416
417     /**
418      * Determine if guest access is allowed
419      *
420      * @return boolean
421      */

422     private final boolean allowsGuest()
423     {
424         return m_allowGuest;
425     }
426
427     /**
428      * Return the login page address
429      *
430      * @return String
431      */

432     private String JavaDoc getLoginPage()
433     {
434        if (m_loginPage == null)
435        {
436           m_loginPage = Application.getLoginPage(m_context);
437        }
438        
439        return m_loginPage;
440     }
441     
442     /**
443      * Delete the servlet filter
444      */

445     public void destroy()
446     {
447     }
448     
449     /**
450      * Process a type 1 NTLM message
451      *
452      * @param type1Msg Type1NTLMMessage
453      * @param req HttpServletRequest
454      * @param resp HttpServletResponse
455      * @param httpSess HttpSession
456      * @exception IOException
457      */

458     private void processType1(Type1NTLMMessage type1Msg, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc resp,
459             HttpSession JavaDoc httpSess) throws IOException JavaDoc
460     {
461         // Debug
462

463         if ( logger.isDebugEnabled())
464             logger.debug("Received type1 " + type1Msg);
465         
466         // Get the existing NTLM details
467

468         NTLMLogonDetails ntlmDetails = null;
469         
470         if ( httpSess != null)
471         {
472             ntlmDetails = (NTLMLogonDetails) httpSess.getAttribute(NTLM_AUTH_DETAILS);
473         }
474         
475         // Check if cached logon details are available
476

477         if ( ntlmDetails != null && ntlmDetails.hasType2Message() && ntlmDetails.hasNTLMHashedPassword() &&
478                 ntlmDetails.hasAuthenticationToken())
479         {
480             // Get the authentication server type2 response
481

482             Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message();
483
484             byte[] type2Bytes = cachedType2.getBytes();
485             String JavaDoc ntlmBlob = "NTLM " + new String JavaDoc(Base64.encodeBase64(type2Bytes));
486
487             // Debug
488

489             if ( logger.isDebugEnabled())
490                 logger.debug("Sending cached NTLM type2 to client - " + cachedType2);
491             
492             // Send back a request for NTLM authentication
493

494             resp.setHeader("WWW-Authenticate", ntlmBlob);
495             resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
496             
497             resp.flushBuffer();
498             return;
499         }
500         else
501         {
502             // Clear any cached logon details
503

504             httpSess.removeAttribute(NTLM_AUTH_DETAILS);
505
506             // Set the 8 byte challenge for the new logon request
507

508             byte[] challenge = null;
509             NTLMPassthruToken authToken = null;
510             
511             if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
512             {
513                 // Generate a random 8 byte challenge
514

515                 challenge = new byte[8];
516                 DataPacker.putIntelLong(m_random.nextLong(), challenge, 0);
517             }
518             else
519             {
520                 // Create an authentication token for the new logon
521

522                 authToken = new NTLMPassthruToken();
523                 
524                 // Run the first stage of the passthru authentication to get the challenge
525

526                 m_authComponent.authenticate( authToken);
527                 
528                 // Get the challenge from the token
529

530                 if ( authToken.getChallenge() != null)
531                     challenge = authToken.getChallenge().getBytes();
532             }
533             
534             // Get the flags from the client request and mask out unsupported features
535

536             int ntlmFlags = type1Msg.getFlags() & NTLM_FLAGS;
537             
538             // Build a type2 message to send back to the client, containing the challenge
539

540             List JavaDoc<TargetInfo> tList = new ArrayList JavaDoc<TargetInfo>();
541             tList.add(new TargetInfo(NTLM.TargetServer, m_srvName));
542             
543             Type2NTLMMessage type2Msg = new Type2NTLMMessage();
544             type2Msg.buildType2(ntlmFlags, m_srvName, challenge, null, tList);
545             
546             // Store the NTLM logon details, cache the type2 message, and token if using passthru
547

548             ntlmDetails = new NTLMLogonDetails();
549             ntlmDetails.setType2Message( type2Msg);
550             ntlmDetails.setAuthenticationToken(authToken);
551             
552             httpSess.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
553             
554             // Debug
555

556             if ( logger.isDebugEnabled())
557                 logger.debug("Sending NTLM type2 to client - " + type2Msg);
558             
559             // Send back a request for NTLM authentication
560

561             byte[] type2Bytes = type2Msg.getBytes();
562             String JavaDoc ntlmBlob = "NTLM " + new String JavaDoc(Base64.encodeBase64(type2Bytes));
563
564             resp.setHeader("WWW-Authenticate", ntlmBlob);
565             resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
566             
567             resp.flushBuffer();
568             return;
569         }
570     }
571     
572     /**
573      * Process a type 3 NTLM message
574      *
575      * @param type3Msg Type3NTLMMessage
576      * @param req HttpServletRequest
577      * @param resp HttpServletResponse
578      * @param httpSess HttpSession
579      * @param chain FilterChain
580      * @exception IOException
581      * @exception ServletException
582      */

583     private void processType3(Type3NTLMMessage type3Msg, HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc resp,
584             HttpSession JavaDoc httpSess, FilterChain JavaDoc chain) throws IOException JavaDoc, ServletException JavaDoc
585     {
586         // Debug
587

588         if ( logger.isDebugEnabled())
589             logger.debug("Received type3 " + type3Msg);
590         
591         // Get the existing NTLM details
592

593         NTLMLogonDetails ntlmDetails = null;
594         User user = null;
595         
596         if ( httpSess != null)
597         {
598             ntlmDetails = (NTLMLogonDetails) httpSess.getAttribute(NTLM_AUTH_DETAILS);
599             user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
600         }
601         
602         // Get the NTLM logon details
603

604         String JavaDoc userName = type3Msg.getUserName();
605         String JavaDoc workstation = type3Msg.getWorkstation();
606         String JavaDoc domain = type3Msg.getDomain();
607         
608         boolean authenticated = false;
609         boolean useNTLM = true;
610         
611         // Check if we are using cached details for the authentication
612

613         if ( user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword())
614         {
615             // Check if the received NTLM hashed password matches the cached password
616

617             byte[] ntlmPwd = type3Msg.getNTLMHash();
618             byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword();
619             
620             if ( ntlmPwd != null)
621             {
622                 if ( ntlmPwd.length == cachedPwd.length)
623                 {
624                     authenticated = true;
625                     for ( int i = 0; i < ntlmPwd.length; i++)
626                     {
627                         if ( ntlmPwd[i] != cachedPwd[i])
628                             authenticated = false;
629                     }
630                 }
631             }
632             
633             // Debug
634

635             if ( logger.isDebugEnabled())
636                 logger.debug("Using cached NTLM hash, authenticated = " + authenticated);
637             
638             try
639             {
640                 // Debug
641

642                 if ( logger.isDebugEnabled())
643                     logger.debug("User " + user.getUserName() + " validate ticket");
644                 
645                 // Validate the user ticket
646

647                 m_authService.validate( user.getTicket());
648                 
649                 // Set the current locale
650

651                 I18NUtil.setLocale(Application.getLanguage(httpSess));
652             }
653             catch (AuthenticationException ex)
654             {
655                 if ( logger.isErrorEnabled())
656                     logger.error("Failed to validate user " + user.getUserName(), ex);
657                 
658                 // Redirect to the login page
659

660                 resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
661                 return;
662             }
663             
664             // Allow the user to access the requested page
665

666             chain.doFilter( req, resp);
667             return;
668         }
669         else
670         {
671             // Check if we are using local MD4 password hashes or passthru authentication
672

673             if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
674             {
675                 // Get the stored MD4 hashed password for the user, or null if the user does not exist
676

677                 String JavaDoc md4hash = m_authComponent.getMD4HashedPassword(userName);
678                 
679                 if ( md4hash != null)
680                 {
681                     // Generate the local encrypted password using the challenge that was sent to the client
682

683                     byte[] p21 = new byte[21];
684                     byte[] md4byts = m_md4Encoder.decodeHash(md4hash);
685                     System.arraycopy(md4byts, 0, p21, 0, 16);
686                     
687                     // Generate the local hash of the password using the same challenge
688

689                     byte[] localHash = null;
690                     
691                     try
692                     {
693                         localHash = m_encryptor.doNTLM1Encryption(p21, ntlmDetails.getChallengeKey());
694                     }
695                     catch (NoSuchAlgorithmException JavaDoc ex)
696                     {
697                     }
698                     
699                     // Validate the password
700

701                     byte[] clientHash = type3Msg.getNTLMHash();
702
703                     if ( clientHash != null && localHash != null && clientHash.length == localHash.length)
704                     {
705                         int i = 0;
706
707                         while ( i < clientHash.length && clientHash[i] == localHash[i])
708                             i++;
709                         
710                         if ( i == clientHash.length)
711                             authenticated = true;
712                     }
713                 }
714                 else
715                 {
716                     // Debug
717

718                     if ( logger.isDebugEnabled())
719                         logger.debug("User " + userName + " does not have Alfresco account");
720                     
721                     // Bypass NTLM authentication and display the logon screen, user account does not
722
// exist in Alfresco
723

724                     authenticated = false;
725                 }
726             }
727             else
728             {
729                 // Passthru mode, send the hashed password details to the passthru authentication server
730

731                 NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken();
732                 authToken.setUserAndPassword( type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1);
733                 
734                 try
735                 {
736                     // Run the second stage of the passthru authentication
737

738                     m_authComponent.authenticate(authToken);
739                     authenticated = true;
740                 }
741                 catch (BadCredentialsException ex)
742                 {
743                     // Debug
744

745                     if ( logger.isDebugEnabled())
746                         logger.debug("Authentication failed, " + ex.getMessage());
747                 }
748                 catch (AuthenticationException ex)
749                 {
750                     // Debug
751

752                     if ( logger.isDebugEnabled())
753                         logger.debug("Authentication failed, " + ex.getMessage());
754                 }
755                 finally
756                 {
757                     // Clear the authentication token from the NTLM details
758

759                     ntlmDetails.setAuthenticationToken(null);
760                 }
761             }
762             
763             // Check if the user has been authenticated, if so then setup the user environment
764

765             if ( authenticated == true)
766             {
767                 UserTransaction JavaDoc tx = m_transactionService.getUserTransaction();
768                 NodeRef homeSpaceRef = null;
769                 
770                 try
771                 {
772                     tx.begin();
773
774                     // Get user details for the authenticated user
775
m_authComponent.setCurrentUser(userName.toLowerCase());
776                     
777                     // The user name used may be a different case to the NTLM supplied user name, read the current
778
// user and use that name
779
userName = m_authComponent.getCurrentUserName();
780                     
781                     // Setup User object and Home space ID etc.
782
NodeRef personNodeRef = m_personService.getPerson(userName);
783                     String JavaDoc currentTicket = m_authService.getCurrentTicket();
784                     user = new User(userName, currentTicket, personNodeRef);
785                     
786                     homeSpaceRef = (NodeRef) m_nodeService.getProperty(
787                             personNodeRef,
788                             ContentModel.PROP_HOMEFOLDER);
789                     user.setHomeSpaceId(homeSpaceRef.getId());
790                     
791                     // commit
792
tx.commit();
793                 }
794                 catch (Throwable JavaDoc ex)
795                 {
796                     try
797                     {
798                         tx.rollback();
799                     }
800                     catch (Exception JavaDoc ex2)
801                     {
802                         logger.error("Failed to rollback transaction", ex2);
803                     }
804                     if(ex instanceof RuntimeException JavaDoc)
805                     {
806                         throw (RuntimeException JavaDoc)ex;
807                     }
808                     else if(ex instanceof IOException JavaDoc)
809                     {
810                         throw (IOException JavaDoc)ex;
811                     }
812                     else if(ex instanceof ServletException JavaDoc)
813                     {
814                         throw (ServletException JavaDoc)ex;
815                     }
816                     else
817                     {
818                         throw new RuntimeException JavaDoc("Authentication setup failed", ex);
819                     }
820                 }
821                 
822                 // Store the user
823

824                 httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
825                 httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
826
827                 // Set the current locale from the Accept-Lanaguage header if available
828

829                 Locale JavaDoc userLocale = parseAcceptLanguageHeader(req, m_languages);
830                 
831                 if ( userLocale != null)
832                 {
833                     httpSess.setAttribute(LOCALE, userLocale);
834                     httpSess.removeAttribute(MESSAGE_BUNDLE);
835                 }
836
837                 // Set the locale using the session
838

839                 I18NUtil.setLocale(Application.getLanguage(httpSess));
840
841                 // Update the NTLM logon details in the session
842

843                 if ( ntlmDetails == null)
844                 {
845                     // No cached NTLM details
846

847                     ntlmDetails = new NTLMLogonDetails( userName, workstation, domain, false, m_srvName);
848                     
849                     httpSess.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
850                     
851                     // Debug
852

853                     if ( logger.isDebugEnabled())
854                         logger.debug("No cached NTLM details, created");
855                     
856                 }
857                 else
858                 {
859                     // Update the cached NTLM details
860

861                     ntlmDetails.setDetails(userName, workstation, domain, false, m_srvName);
862                     ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
863
864                     // Debug
865

866                     if ( logger.isDebugEnabled())
867                         logger.debug("Updated cached NTLM details");
868                 }
869                 
870                 // Debug
871

872                 if ( logger.isDebugEnabled())
873                     logger.debug("User logged on via NTLM, " + ntlmDetails);
874
875                 // If the original URL requested was the login page then redirect to the browse view
876

877                 if (req.getRequestURI().endsWith(getLoginPage()) == true)
878                 {
879                     // Debug
880

881                     if ( logger.isDebugEnabled())
882                         logger.debug("Login page requested, redirecting to browse page");
883
884                     // Redirect to the browse view
885

886                     resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
887                     return;
888                 }
889                 else
890                 {
891                     // Allow the user to access the requested page
892

893                     chain.doFilter( req, resp);
894                     return;
895                 }
896             }
897             else
898             {
899                 // Check if NTLM should be used, switched off if the user does not exist in the Alfresco
900
// user database
901

902                 if (useNTLM == true)
903                 {
904                     // Remove any existing session and NTLM details from the session
905

906                     httpSess.removeAttribute(NTLM_AUTH_SESSION);
907                     httpSess.removeAttribute(NTLM_AUTH_DETAILS);
908                     
909                     // Force the logon to start again
910

911                     resp.setHeader("WWW-Authenticate", "NTLM");
912                     resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
913                     
914                     resp.flushBuffer();
915                     return;
916                 }
917                 else
918                 {
919                     // Debug
920

921                     if ( logger.isDebugEnabled())
922                         logger.debug("Redirecting to login page");
923
924                     // Redirect to the login page
925

926                     resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
927                     return;
928                 }
929             }
930         }
931     }
932 }
933
Popular Tags