KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > bin > filters > ntlm > NtlmHttpFilter


1 /* jcifs smb client library in Java
2  * Copyright (C) 2002 "Michael B. Allen" <jcifs at samba dot org>
3  * "Jason Pugsley" <jcifs at samba dot org>
4  * "skeetz" <jcifs at samba dot org>
5  * "Eric Glass" <jcifs at samba dot org>
6  * and Marcel, Thomas, ...
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
package org.jahia.bin.filters.ntlm;
22
23 import jcifs.Config;
24 import jcifs.UniAddress;
25 import jcifs.http.NtlmSsp;
26 import jcifs.smb.NtlmChallenge;
27 import jcifs.smb.NtlmPasswordAuthentication;
28 import jcifs.smb.SmbAuthException;
29 import jcifs.smb.SmbSession;
30 import jcifs.util.Base64;
31 import jcifs.util.LogStream;
32
33 import javax.servlet.Filter JavaDoc;
34 import javax.servlet.FilterChain JavaDoc;
35 import javax.servlet.FilterConfig JavaDoc;
36 import javax.servlet.ServletException JavaDoc;
37 import javax.servlet.ServletRequest JavaDoc;
38 import javax.servlet.ServletResponse JavaDoc;
39 import javax.servlet.http.HttpServletRequest JavaDoc;
40 import javax.servlet.http.HttpServletResponse JavaDoc;
41 import javax.servlet.http.HttpSession JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.util.Enumeration JavaDoc;
44
45 /**
46  * This servlet Filter can be used to negotiate password hashes with
47  * MSIE clients using NTLM SSP. This is similar to <tt>Authentication:
48  * BASIC</tt> but weakly encrypted and without requiring the user to re-supply
49  * authentication credentials.
50  * <p>
51  * Read <a HREF="../../../ntlmhttpauth.html">jCIFS NTLM HTTP Authentication and the Network Explorer Servlet</a> for complete details.
52  *
53  * This is a slightly modified version from the original to make the
54  * skipAuthentification parameter configurable, as it was hardcoded
55  * in the original.
56  */

57
58 public class NtlmHttpFilter implements Filter JavaDoc {
59
60     private static LogStream log = LogStream.getInstance();
61
62     private String JavaDoc defaultDomain;
63     private String JavaDoc domainController;
64     private boolean loadBalance;
65     private boolean enableBasic;
66     private boolean useBasic;
67     private boolean insecureBasic;
68     private String JavaDoc realm;
69     private boolean skipAuthentification;
70
71     public void init( FilterConfig JavaDoc filterConfig ) throws ServletException JavaDoc {
72         String JavaDoc name;
73         int level;
74
75         /* Set jcifs properties we know we want; soTimeout and cachePolicy to 10min.
76          */

77         Config.setProperty( "jcifs.smb.client.soTimeout", "300000" );
78         Config.setProperty( "jcifs.netbios.cachePolicy", "1200" );
79
80         Enumeration JavaDoc e = filterConfig.getInitParameterNames();
81         while( e.hasMoreElements() ) {
82             name = (String JavaDoc)e.nextElement();
83             if( name.startsWith( "jcifs." )) {
84                 Config.setProperty( name, filterConfig.getInitParameter( name ));
85             }
86         }
87         defaultDomain = Config.getProperty("jcifs.smb.client.domain");
88         domainController = Config.getProperty( "jcifs.http.domainController" );
89         if( domainController == null ) {
90             domainController = defaultDomain;
91             loadBalance = Config.getBoolean( "jcifs.http.loadBalance", true );
92         }
93         enableBasic = Boolean.valueOf(
94                 Config.getProperty("jcifs.http.enableBasic")).booleanValue();
95         useBasic = Boolean.valueOf(
96                 Config.getProperty("jcifs.http.useBasic")).booleanValue();
97         insecureBasic = Boolean.valueOf(
98                 Config.getProperty("jcifs.http.insecureBasic")).booleanValue();
99         realm = Config.getProperty("jcifs.http.basicRealm");
100         if (realm == null) realm = "jCIFS";
101
102         skipAuthentification = Boolean.valueOf(
103                 Config.getProperty("jcifs.http.skipAuthentification")).booleanValue();
104
105         if(( level = Config.getInt( "jcifs.util.loglevel", -1 )) != -1 ) {
106             LogStream.setLevel( level );
107         }
108         if( log.level > 2 ) {
109             try {
110                 Config.store( log, "JCIFS PROPERTIES" );
111             } catch( IOException JavaDoc ioe ) {
112             }
113         }
114     }
115
116     public void destroy() {
117     }
118
119     /**
120      * This method simply calls <tt>negotiate( req, resp, false )</tt>
121      * and then <tt>chain.doFilter</tt>. You can override and call
122      * negotiate manually to achive a variety of different behavior.
123      */

124     public void doFilter( ServletRequest JavaDoc request,
125                 ServletResponse JavaDoc response,
126                 FilterChain JavaDoc chain ) throws IOException JavaDoc, ServletException JavaDoc {
127         HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc)request;
128         HttpServletResponse JavaDoc resp = (HttpServletResponse JavaDoc)response;
129         NtlmPasswordAuthentication ntlm;
130
131         if ((ntlm = negotiate( req, resp, skipAuthentification )) == null) {
132             if (!skipAuthentification) {
133                 return;
134             }
135         }
136
137         Boolean JavaDoc isBasicBool = (Boolean JavaDoc) request.getAttribute("isBasic");
138         if (isBasicBool == null) {
139             isBasicBool = new Boolean JavaDoc(false);
140         }
141         boolean useNtlmRequest = false;
142         if (ntlm != null) {
143             useNtlmRequest = true;
144         }
145         if (isBasicBool.booleanValue() && !useBasic) {
146             useNtlmRequest = false;
147         }
148
149         if (useNtlmRequest) {
150             req.setAttribute("ntlmPrincipal", ntlm);
151             req.setAttribute("ntlmAuthType", "NTLM");
152             chain.doFilter( req, response );
153         } else {
154             chain.doFilter(req, response);
155         }
156     }
157
158     /**
159      * Negotiate password hashes with MSIE clients using NTLM SSP
160      * @param req The servlet request
161      * @param resp The servlet response
162      * @param skipAuthentication If true the negotiation is only done if it is
163      * initiated by the client (MSIE post requests after successful NTLM SSP
164      * authentication). If false and the user has not been authenticated yet
165      * the client will be forced to send an authentication (server sends
166      * HttpServletResponse.SC_UNAUTHORIZED).
167      * @return True if the negotiation is complete, otherwise false
168      */

169     protected NtlmPasswordAuthentication negotiate( HttpServletRequest JavaDoc req,
170                 HttpServletResponse JavaDoc resp,
171                 boolean skipAuthentication ) throws IOException JavaDoc, ServletException JavaDoc {
172         UniAddress dc;
173         String JavaDoc msg;
174         NtlmPasswordAuthentication ntlm = null;
175         msg = req.getHeader( "Authorization" );
176         boolean offerBasic = enableBasic && (insecureBasic || req.isSecure());
177         boolean isBasic = false;
178
179         if( msg != null && (msg.startsWith( "NTLM " ) ||
180                     (offerBasic && msg.startsWith("Basic ")))) {
181             if (msg.startsWith("NTLM ")) {
182                 HttpSession JavaDoc ssn = req.getSession();
183                 byte[] challenge;
184
185                 if( loadBalance ) {
186                     NtlmChallenge chal = (NtlmChallenge)ssn.getAttribute( "NtlmHttpChal" );
187                     if( chal == null ) {
188                         chal = SmbSession.getChallengeForDomain();
189                         ssn.setAttribute( "NtlmHttpChal", chal );
190                     }
191                     dc = chal.dc;
192                     challenge = chal.challenge;
193                 } else {
194                     dc = UniAddress.getByName( domainController, true );
195                     challenge = SmbSession.getChallenge( dc );
196                 }
197
198                 if(( ntlm = NtlmSsp.authenticate( req, resp, challenge )) == null ) {
199                     return null;
200                 }
201                 /* negotiation complete, remove the challenge object */
202                 ssn.removeAttribute( "NtlmHttpChal" );
203             } else {
204                 req.setAttribute("isBasic", new Boolean JavaDoc(true));
205                 isBasic = true;
206                 String JavaDoc auth = new String JavaDoc(Base64.decode(msg.substring(6)),
207                         "US-ASCII");
208                 int index = auth.indexOf(':');
209                 String JavaDoc user = (index != -1) ? auth.substring(0, index) : auth;
210                 String JavaDoc password = (index != -1) ? auth.substring(index + 1) :
211                         "";
212                 index = user.indexOf('\\');
213                 if (index == -1) index = user.indexOf('/');
214                 String JavaDoc domain = (index != -1) ? user.substring(0, index) :
215                         defaultDomain;
216                 user = (index != -1) ? user.substring(index + 1) : user;
217                 ntlm = new NtlmPasswordAuthentication(domain, user, password);
218                 dc = UniAddress.getByName( domainController, true );
219             }
220             try {
221                 if ((isBasic) && (!useBasic)) {
222                     return ntlm;
223                 }
224                 SmbSession.logon( dc, ntlm );
225
226                 if( log.level > 2 ) {
227                     log.println( "NtlmHttpFilter: " + ntlm +
228                             " successfully authenticated against " + dc );
229                 }
230             } catch( SmbAuthException sae ) {
231                 if( log.level > 1 ) {
232                     log.println( "NtlmHttpFilter: " + ntlm.getName() +
233                             ": 0x" + jcifs.util.Hexdump.toHexString( sae.getNtStatus(), 8 ) +
234                             ": " + sae );
235                 }
236                 if( sae.getNtStatus() == sae.NT_STATUS_ACCESS_VIOLATION ) {
237                     /* Server challenge no longer valid for
238                      * externally supplied password hashes.
239                      */

240                     HttpSession JavaDoc ssn = req.getSession(false);
241                     if (ssn != null) {
242                         ssn.removeAttribute( "NtlmHttpAuth" );
243                     }
244                 }
245                 resp.setHeader( "WWW-Authenticate", "NTLM" );
246                 if (offerBasic) {
247                     resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +
248                             realm + "\"");
249                 }
250                 resp.setContentLength(0); /* Marcel Feb-15-2005 */
251                 resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
252                 resp.flushBuffer();
253                 return null;
254             }
255             req.getSession().setAttribute( "NtlmHttpAuth", ntlm );
256         } else {
257             if (!skipAuthentication) {
258                 HttpSession JavaDoc ssn = req.getSession(false);
259                 if (ssn == null || (ntlm = (NtlmPasswordAuthentication)
260                             ssn.getAttribute("NtlmHttpAuth")) == null) {
261                     resp.setHeader( "WWW-Authenticate", "NTLM" );
262                     if (offerBasic) {
263                         resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +
264                                 realm + "\"");
265                     }
266                     resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
267                     resp.flushBuffer();
268                     return null;
269                 }
270             }
271         }
272
273         return ntlm;
274     }
275
276     // Added by cgross to work with weblogic 6.1.
277
public void setFilterConfig( FilterConfig JavaDoc f ) {
278         try {
279             init( f );
280         } catch( Exception JavaDoc e ) {
281             e.printStackTrace();
282         }
283     }
284     public FilterConfig JavaDoc getFilterConfig() {
285         return null;
286     }
287 }
Popular Tags