KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > http > 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  */

22
23 package jcifs.http;
24
25 import java.io.*;
26 import java.util.Enumeration JavaDoc;
27 import java.net.UnknownHostException JavaDoc;
28 import javax.servlet.*;
29 import javax.servlet.http.*;
30 import jcifs.*;
31 import jcifs.smb.SmbSession;
32 import jcifs.smb.NtlmChallenge;
33 import jcifs.smb.NtlmPasswordAuthentication;
34 import jcifs.smb.SmbAuthException;
35 import jcifs.util.Base64;
36 import jcifs.util.LogStream;
37 import jcifs.netbios.NbtAddress;
38
39 /**
40  * This servlet Filter can be used to negotiate password hashes with
41  * MSIE clients using NTLM SSP. This is similar to <tt>Authentication:
42  * BASIC</tt> but weakly encrypted and without requiring the user to re-supply
43  * authentication credentials.
44  * <p>
45  * Read <a HREF="../../../ntlmhttpauth.html">jCIFS NTLM HTTP Authentication and the Network Explorer Servlet</a> for complete details.
46  */

47
48 public class NtlmHttpFilter implements Filter {
49
50     private static LogStream log = LogStream.getInstance();
51
52     private String JavaDoc defaultDomain;
53     private String JavaDoc domainController;
54     private boolean loadBalance;
55     private boolean enableBasic;
56     private boolean insecureBasic;
57     private String JavaDoc realm;
58
59     public void init( FilterConfig filterConfig ) throws ServletException {
60         String JavaDoc name;
61         int level;
62
63         /* Set jcifs properties we know we want; soTimeout and cachePolicy to 10min.
64          */

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

107     public void doFilter( ServletRequest request,
108                 ServletResponse response,
109                 FilterChain chain ) throws IOException, ServletException {
110         HttpServletRequest req = (HttpServletRequest)request;
111         HttpServletResponse resp = (HttpServletResponse)response;
112         NtlmPasswordAuthentication ntlm;
113
114         if ((ntlm = negotiate( req, resp, false )) == null) {
115             return;
116         }
117
118         chain.doFilter( new NtlmHttpServletRequest( req, ntlm ), response );
119     }
120
121     /**
122      * Negotiate password hashes with MSIE clients using NTLM SSP
123      * @param req The servlet request
124      * @param resp The servlet response
125      * @param skipAuthentication If true the negotiation is only done if it is
126      * initiated by the client (MSIE post requests after successful NTLM SSP
127      * authentication). If false and the user has not been authenticated yet
128      * the client will be forced to send an authentication (server sends
129      * HttpServletResponse.SC_UNAUTHORIZED).
130      * @return True if the negotiation is complete, otherwise false
131      */

132     protected NtlmPasswordAuthentication negotiate( HttpServletRequest req,
133                 HttpServletResponse resp,
134                 boolean skipAuthentication ) throws IOException, ServletException {
135         UniAddress dc;
136         String JavaDoc msg;
137         NtlmPasswordAuthentication ntlm = null;
138         msg = req.getHeader( "Authorization" );
139         boolean offerBasic = enableBasic && (insecureBasic || req.isSecure());
140
141         if( msg != null && (msg.startsWith( "NTLM " ) ||
142                     (offerBasic && msg.startsWith("Basic ")))) {
143             if (msg.startsWith("NTLM ")) {
144                 HttpSession ssn = req.getSession();
145                 byte[] challenge;
146
147                 if( loadBalance ) {
148                     NtlmChallenge chal = (NtlmChallenge)ssn.getAttribute( "NtlmHttpChal" );
149                     if( chal == null ) {
150                         chal = SmbSession.getChallengeForDomain();
151                         ssn.setAttribute( "NtlmHttpChal", chal );
152                     }
153                     dc = chal.dc;
154                     challenge = chal.challenge;
155                 } else {
156                     dc = UniAddress.getByName( domainController, true );
157                     challenge = SmbSession.getChallenge( dc );
158                 }
159
160                 if(( ntlm = NtlmSsp.authenticate( req, resp, challenge )) == null ) {
161                     return null;
162                 }
163                 /* negotiation complete, remove the challenge object */
164                 ssn.removeAttribute( "NtlmHttpChal" );
165             } else {
166                 String JavaDoc auth = new String JavaDoc(Base64.decode(msg.substring(6)),
167                         "US-ASCII");
168                 int index = auth.indexOf(':');
169                 String JavaDoc user = (index != -1) ? auth.substring(0, index) : auth;
170                 String JavaDoc password = (index != -1) ? auth.substring(index + 1) :
171                         "";
172                 index = user.indexOf('\\');
173                 if (index == -1) index = user.indexOf('/');
174                 String JavaDoc domain = (index != -1) ? user.substring(0, index) :
175                         defaultDomain;
176                 user = (index != -1) ? user.substring(index + 1) : user;
177                 ntlm = new NtlmPasswordAuthentication(domain, user, password);
178                 dc = UniAddress.getByName( domainController, true );
179             }
180             try {
181
182                 SmbSession.logon( dc, ntlm );
183
184                 if( log.level > 2 ) {
185                     log.println( "NtlmHttpFilter: " + ntlm +
186                             " successfully authenticated against " + dc );
187                 }
188             } catch( SmbAuthException sae ) {
189                 if( log.level > 1 ) {
190                     log.println( "NtlmHttpFilter: " + ntlm.getName() +
191                             ": 0x" + jcifs.util.Hexdump.toHexString( sae.getNtStatus(), 8 ) +
192                             ": " + sae );
193                 }
194                 if( sae.getNtStatus() == sae.NT_STATUS_ACCESS_VIOLATION ) {
195                     /* Server challenge no longer valid for
196                      * externally supplied password hashes.
197                      */

198                     HttpSession ssn = req.getSession(false);
199                     if (ssn != null) {
200                         ssn.removeAttribute( "NtlmHttpAuth" );
201                     }
202                 }
203                 resp.setHeader( "WWW-Authenticate", "NTLM" );
204                 if (offerBasic) {
205                     resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +
206                             realm + "\"");
207                 }
208                 resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
209                 resp.setContentLength(0); /* Marcel Feb-15-2005 */
210                 resp.flushBuffer();
211                 return null;
212             }
213             req.getSession().setAttribute( "NtlmHttpAuth", ntlm );
214         } else {
215             if (!skipAuthentication) {
216                 HttpSession ssn = req.getSession(false);
217                 if (ssn == null || (ntlm = (NtlmPasswordAuthentication)
218                             ssn.getAttribute("NtlmHttpAuth")) == null) {
219                     resp.setHeader( "WWW-Authenticate", "NTLM" );
220                     if (offerBasic) {
221                         resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +
222                                 realm + "\"");
223                     }
224                     resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
225                     resp.setContentLength(0);
226                     resp.flushBuffer();
227                     return null;
228                 }
229             }
230         }
231
232         return ntlm;
233     }
234
235     // Added by cgross to work with weblogic 6.1.
236
public void setFilterConfig( FilterConfig f ) {
237         try {
238             init( f );
239         } catch( Exception JavaDoc e ) {
240             e.printStackTrace();
241         }
242     }
243     public FilterConfig getFilterConfig() {
244         return null;
245     }
246 }
247
248
Popular Tags