KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > matuschek > http > NTLMAuthorization


1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15  */

16
17 /*
18  * NTLMAuthorizationHandler.java
19  * Copyright (C) 2002 Luigi Dragone
20  *
21  */

22
23 package net.matuschek.http;
24
25 import java.io.*;
26 import java.security.Provider JavaDoc;
27 import java.security.Security JavaDoc;
28
29 import com.luigidragone.net.ntlm.NTLM;
30 import net.matuschek.util.Base64;
31
32 /**
33  * <p>
34  * This is an NTLM protocol authorization module for
35  * <a HREF="http://www.matuschek.net/software/jobo/index.html">JOBO</a>.
36  * </p>
37  * <p>
38  * NTLM is a Microsoft proprietary network authentication protocol used in many
39  * situations and HTTPClient is a versatile and extendible component for
40  * implementing HTTP client applications.
41  * </p>
42  * <p>
43  * This class relies on {@link NTLM NTLM} class. It also requires a JCE
44  * compliant library (e.g., <a HREF="http://www.cryptix.org/"> Cryptix JCE</a>)
45  * that implements MD4 and DES algorithms.
46  * </p>
47  * To perform an authentication the following information are needed:
48  * <ul>
49  * <li>the host name (with its own domain);</li>
50  * <li>the user name (with its own domain);</li>
51  * <li>the user password.</li>
52  * </ul>
53  * Alternatively, the user password can be replaced with its Lan Manager and
54  * NT hashed versions. On a Windows system these can be collected in the registry
55  * (with a bit of JNI, so), otherwise can be extracted from a SAMBA password
56  * file.<br>
57  * Notice that the host and user domain could not be the same.
58  * </p>
59  *
60  * @author Luigi Dragone (<a HREF="mailto:luigi@luigidragone. com">luigi@luigidragone.com</a>)
61  * @author oliver_schmidt
62  *
63  * @see <a HREF="http://www.innovation.ch/java/ntlm.html">NTLM Authentication Scheme for HTTP</a>
64  * @see <a HREF="http://www.innovation.ch/">HTTPClient</a>
65  * @see <a HREF="http://rfc.net/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
66  * @see <a HREF="http://rfc.net/rfc2617.html">HTTP Authentication: Basic and Digest Access Authentication</a>
67  *
68  * @version $Id: NTLMAuthorization.java,v 1.2 2003/05/23 17:00:00 oliver_schmidt
69  * Exp $
70  * </p>
71  */

72
73 public class NTLMAuthorization implements Serializable, Cloneable JavaDoc {
74
75   // if nothing in data structure has changed, keep this UID:
76
// otherwise calculate new
77
static final long serialVersionUID = -1347968095010834437L;
78     
79   public class MissingJceException extends Exception JavaDoc {
80     private static final long serialVersionUID = -6580761514651447918L;
81     MissingJceException(String JavaDoc msg) { super(msg); }
82   };
83     
84   public static final String JavaDoc NTLM_TAG = "NTLM";
85   public static final String JavaDoc PROXY_AUTHENTICATE_HEADER = "Proxy-Authenticate";
86   public static final String JavaDoc WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
87     
88   transient byte[] nonce = null;
89   private String JavaDoc host = null;
90   private String JavaDoc user = null;
91   private String JavaDoc hostDomain = null;
92   private String JavaDoc userDomain = null;
93   private String JavaDoc securityProvider = null;
94   private byte[] lmPassword = null;
95   private byte[] ntPassword = null;
96   
97   private static boolean securityProviderAdded = false;
98   
99     /**
100      * Default constructor requires setting of attributes.
101      */

102   public NTLMAuthorization() {
103   }
104
105   /**
106    * <p>
107    * Build an NTLM authorization handler for the specified authentication credentials.
108    * </p>
109    * <p>
110    * All the arguments are mandatory (null value are not allowed).
111    * </p>
112    *
113    * @param host the name of the host that is authenticating
114    * @param hostDomain the name of the domain to which the host belongs
115    * @param user the name of the user
116    * @param userDomain the name of the domain to which the user belongs
117    * @param lmPassword a 16-bytes array containing the Lan Manager hashed password
118    * @param ntPassword a 16-bytes array containing the NT hashed password
119    *
120    * @exception IllegalArgumentException if a supplied argument is invalid
121    */

122   public NTLMAuthorization(String JavaDoc host, String JavaDoc hostDomain, String JavaDoc user, String JavaDoc userDomain, byte[] lmPassword, byte[] ntPassword) {
123     setHost(host);
124     setHostDomain(hostDomain);
125     setUser(user);
126     setUserDomain(userDomain);
127     setLmPasswordHash(lmPassword);
128     setNtPasswordHash(ntPassword);
129   }
130
131   /**
132    * <p>
133    * Build an NTLM authorization handler for the specified authentication credentials.
134    * </p>
135    * <p>
136    * All the arguments are mandatory (null value are not allowed).
137    * </p>
138    *
139    * @param host the name of the host that is authenticating
140    * @param hostDomain the name of the domain to which the host belongs
141    * @param user the name of the user
142    * @param userDomain the name of the domain to which the user belongs
143    * @param password the user's password
144    *
145    * @exception IllegalArgumentException if a supplied argument is invalid
146    * @exception javax.crypto.NoSuchPaddingException if there isn't any suitable padding method
147    * @exception NoSuchAlgorithmException if there isn't any suitable cipher algorithm
148    */

149   public NTLMAuthorization(String JavaDoc host, String JavaDoc hostDomain, String JavaDoc user, String JavaDoc userDomain, String JavaDoc password) throws MissingJceException {
150     setHost(host);
151     setHostDomain(hostDomain);
152     setUser(user);
153     setUserDomain(userDomain);
154     setPassword(password);
155   }
156
157   public String JavaDoc getResponse() throws MissingJceException {
158     try {
159         return new String JavaDoc(Base64.encode(NTLM.formatResponse(host, user, userDomain, lmPassword, ntPassword, nonce)));
160     } catch (Exception JavaDoc e) {
161         throw new MissingJceException(e.getMessage());
162     }
163   }
164   
165   public String JavaDoc getRequest() throws IOException {
166     return new String JavaDoc(Base64.encode(NTLM.formatRequest(host, hostDomain)));
167   }
168
169   public void extractNonce(String JavaDoc challenge) throws java.io.IOException JavaDoc {
170     nonce = null;
171     try {
172       // String challenge = parm1.getHeader(PROXY_AUTHENTICATE_HEADER);
173
if((challenge != null) && challenge.startsWith(NTLM_TAG) && challenge.length() > 4)
174         nonce = NTLM.getNonce(Base64.decode(challenge.substring(challenge.indexOf(' ') + 1).trim()));
175 /* else {
176         challenge = parm1.getHeader(WWW_AUTHENTICATE_HEADER);
177         if((challenge != null) && challenge.startsWith(NTLM_TAG) && challenge.length() > 4)
178           nonce = NTLM.getNonce(Codecs.base64Decode(challenge.substring(challenge.indexOf(' ') + 1).trim()).getBytes());
179       } */

180     } catch(Exception JavaDoc ex) {
181       ex.printStackTrace();
182     }
183   }
184
185 public void setHost(String JavaDoc host) {
186     if(host == null)
187       throw new IllegalArgumentException JavaDoc("host : null value not allowed");
188     this.host = host;
189 }
190
191 public String JavaDoc getHost() {
192     return host;
193 }
194
195 public void setHostDomain(String JavaDoc hostDomain) {
196     if(hostDomain == null)
197       throw new IllegalArgumentException JavaDoc("hostDomain : null value not allowed");
198     this.hostDomain = hostDomain;
199 }
200
201 public String JavaDoc getHostDomain() {
202     return hostDomain;
203 }
204
205 public void setUser(String JavaDoc user) {
206     if(user == null)
207       throw new IllegalArgumentException JavaDoc("user : null value not allowed");
208     this.user = user;
209 }
210
211 public String JavaDoc getUser() {
212     return user;
213 }
214
215 public void setUserDomain(String JavaDoc userDomain) {
216     if(userDomain == null)
217       throw new IllegalArgumentException JavaDoc("userDomain : null value not allowed");
218     this.userDomain = userDomain;
219 }
220
221 public void setPassword(String JavaDoc password) throws MissingJceException {
222     setLmPassword(password);
223     setNtPassword(password);
224 }
225
226 public String JavaDoc getUserDomain() {
227     return userDomain;
228 }
229
230 public String JavaDoc getDomain() {
231     return userDomain;
232 }
233 public void setDomain(String JavaDoc domain) {
234     setUserDomain(domain);
235     setHostDomain(domain);
236 }
237
238 public void setLmPassword(String JavaDoc password) throws MissingJceException {
239     addStandardSecurityProvider();
240     if(password == null)
241       throw new IllegalArgumentException JavaDoc("lmPassword : null value not allowed");
242     try {
243         this.lmPassword = NTLM.computeLMPassword(password);
244     } catch (Exception JavaDoc e) {
245         throw new MissingJceException(e.getMessage());
246     }
247 }
248
249 public String JavaDoc getLmPassword() { return lmPassword.toString(); };
250 public String JavaDoc getNtPassword() { return ntPassword.toString(); };
251 public String JavaDoc getPassword() { return ntPassword.toString(); };
252 public byte[] getLmPasswordHash() { return lmPassword; };
253 public byte[] getNtPasswordHash() { return ntPassword; };
254
255 public void setLmPasswordHash(byte[] password) {
256     if(password == null)
257       throw new IllegalArgumentException JavaDoc("lmPassword : null value not allowed");
258     if(password.length != 16)
259       throw new IllegalArgumentException JavaDoc("lmPassword : illegal size");
260     this.lmPassword = password;
261 }
262
263 public void setNtPassword(String JavaDoc password) throws MissingJceException {
264     addStandardSecurityProvider();
265     if(password == null)
266       throw new IllegalArgumentException JavaDoc("ntPassword : null value not allowed");
267     try {
268         this.ntPassword = NTLM.computeNTPassword(password);
269     } catch (Exception JavaDoc e) {
270         throw new MissingJceException(e.getMessage());
271     }
272 }
273
274 public void setNtPasswordHash(byte[] password) {
275     if(password == null)
276       throw new IllegalArgumentException JavaDoc("ntPassword : null value not allowed");
277     if(password.length != 16)
278       throw new IllegalArgumentException JavaDoc("ntPassword : illegal size");
279     this.ntPassword = password;
280 }
281
282
283 public String JavaDoc toString() {
284     return "Host=" + host
285             + ", HostDomain=" + hostDomain
286             + ", User=" + user
287             + ", UserDomain=" + userDomain
288             + ", lmPwd=" + lmPassword
289             + ", ntPwd=" + ntPassword
290             + ", Nonce=" + nonce;
291 }
292
293
294 /**
295  * Adds a standard security provider "cryptix.jce. provider.CryptixCrypto".
296  */

297 public final void addStandardSecurityProvider() {
298     if (!securityProviderAdded) {
299         try {
300             setSecurityProvider("cryptix.jce.provider.CryptixCrypto");
301         } catch (Exception JavaDoc ex) {
302             // Ignore errors. Hopefully a provider is available.
303
}
304         securityProviderAdded = true;
305     }
306 }
307     
308
309 public void setSecurityProvider(String JavaDoc securityProviderClassName) throws ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc {
310     this.securityProvider = securityProviderClassName;
311     if(securityProviderClassName != null) {
312         Class JavaDoc securityProvider = Class.forName(securityProviderClassName);
313         Security.addProvider((Provider JavaDoc)securityProvider.newInstance());
314         securityProviderAdded = true;
315     }
316 }
317
318 public String JavaDoc getSecurityProvider() {
319     return securityProvider;
320 }
321
322 public boolean isComplete() {
323     return lmPassword != null && ntPassword != null && hostDomain!= null && userDomain != null && user != null;
324 }
325
326 public void writeToFile(String JavaDoc filename) throws FileNotFoundException, IOException {
327     ObjectOutputStream os = new ObjectOutputStream(
328         new FileOutputStream(filename));
329     os.writeObject(this);
330     os.close();
331 }
332
333 public static NTLMAuthorization readFromFile(String JavaDoc filename) throws OptionalDataException, ClassNotFoundException JavaDoc, IOException {
334     ObjectInputStream is = new ObjectInputStream(new FileInputStream(filename));
335     NTLMAuthorization auth = (NTLMAuthorization)is.readObject();
336     return auth;
337 }
338
339 public void setFilename(String JavaDoc filename) throws OptionalDataException, IOException, ClassNotFoundException JavaDoc, InstantiationException JavaDoc, IllegalAccessException JavaDoc {
340     NTLMAuthorization auth = readFromFile(filename);
341     host = auth.host;
342     hostDomain = auth.hostDomain;
343     lmPassword = auth.lmPassword;
344     ntPassword = auth.ntPassword;
345     setSecurityProvider(auth.securityProvider);
346     user = auth.user;
347     userDomain = auth.userDomain;
348 }
349 public String JavaDoc getFilename() { return null; }
350
351 public static void main(String JavaDoc[] args) {
352     NTLMAuthorization auth = new NTLMAuthorization();
353     try {
354         String JavaDoc filename = "";
355         for (int i = 0; i < args.length; i++) {
356             String JavaDoc s = args[i];
357             int sep = s.indexOf("=");
358             String JavaDoc left = sep >= 0 ? s.substring(0, sep).toLowerCase() : null;
359             String JavaDoc right = sep >= 0 ? s.substring(sep + 1) : s;
360         
361             if (left == null) { filename = s;}
362             else if (left.equals("-domain")) { auth.setDomain(right); }
363             else if (left.equals("-host")) { auth.setHost(right); }
364             else if (left.equals("-hostdomain")) { auth.setHostDomain(right); }
365             else if (left.equals("-lmpassword")) { auth.setLmPassword(right); }
366             else if (left.equals("-ntpassword")) { auth.setNtPassword(right); }
367             else if (left.equals("-password")) { auth.setPassword(right); }
368             else if (left.equals("-securityprovider")) { auth.setSecurityProvider(right); }
369             else if (left.equals("-user")) { auth.setUser(right); }
370             else if (left.equals("-userDomain")) { auth.setUserDomain(right); }
371             else {
372                 System.err.println("Unrecognized parameter: " + left);
373             }
374         }
375         if (!auth.isComplete() || filename == null) {
376             System.err.println("Syntax: <filename> <-parameter=value>*");
377             System.err.println("Required parameters: domain | (hostDomain, userDomain),");
378             System.err.println(" user,");
379             System.err.println(" password | (lmPassword, ntPassword)");
380             System.err.println("Optional parameters: securityprovider\n");
381             System.err.println("Example : ntAuth.dat -user=NTLM -domain=TEAMSPORT -password=NTLMNTLM");
382             System.exit(0);
383         }
384     
385         auth.writeToFile(filename);
386         System.out.println(filename + " successfully written.");
387         
388         auth = readFromFile(filename);
389         System.out.println(filename + " successfully read:");
390         System.out.println(auth);
391         
392     } catch (Exception JavaDoc e) {
393         e.printStackTrace();
394     }
395 }
396
397 public Object JavaDoc clone() {
398     try {
399         return super.clone();
400     } catch (CloneNotSupportedException JavaDoc e) {
401         return null; // Canīt happen
402
}
403 }
404
405 }
406
Popular Tags