001: /*
002: * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.net.www.protocol.http;
027:
028: import java.util.Arrays;
029: import java.util.StringTokenizer;
030: import java.util.Random;
031:
032: import sun.net.www.HeaderParser;
033:
034: import java.io.*;
035: import javax.crypto.*;
036: import javax.crypto.spec.*;
037: import java.security.*;
038: import java.net.*;
039:
040: /**
041: * NTLMAuthentication:
042: *
043: * @author Michael McMahon
044: */
045:
046: class NTLMAuthentication extends AuthenticationInfo {
047:
048: private static final long serialVersionUID = 100L;
049:
050: static final char NTLM_AUTH = 'N';
051: private String hostname;
052: private static String defaultDomain; /* Domain to use if not specified by user */
053:
054: static {
055:
056: defaultDomain = (String) java.security.AccessController
057: .doPrivileged(new java.security.PrivilegedAction() {
058: public Object run() {
059: String s = System
060: .getProperty("http.auth.ntlm.domain");
061: if (s == null)
062: return "domain";
063: return s;
064: }
065: });
066: };
067:
068: private void init0() {
069:
070: hostname = (String) java.security.AccessController
071: .doPrivileged(new java.security.PrivilegedAction() {
072: public Object run() {
073: String localhost;
074: try {
075: localhost = InetAddress.getLocalHost()
076: .getHostName().toUpperCase();
077: } catch (UnknownHostException e) {
078: localhost = "localhost";
079: }
080: return localhost;
081: }
082: });
083: int x = hostname.indexOf('.');
084: if (x != -1) {
085: hostname = hostname.substring(0, x);
086: }
087: }
088:
089: String username;
090: String ntdomain;
091: String password;
092:
093: /**
094: * Create a NTLMAuthentication:
095: * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
096: * If this notation is not used, then the domain will be taken
097: * from a system property: "http.auth.ntlm.domain".
098: */
099: public NTLMAuthentication(boolean isProxy, URL url,
100: PasswordAuthentication pw) {
101: super (isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
102: NTLM_AUTH, url, "");
103: init(pw);
104: }
105:
106: private void init(PasswordAuthentication pw) {
107: this .pw = pw;
108: if (pw != null) {
109: String s = pw.getUserName();
110: int i = s.indexOf('\\');
111: if (i == -1) {
112: username = s;
113: ntdomain = defaultDomain;
114: } else {
115: ntdomain = s.substring(0, i).toUpperCase();
116: username = s.substring(i + 1);
117: }
118: password = new String(pw.getPassword());
119: } else {
120: /* credentials will be acquired from OS */
121: username = null;
122: ntdomain = null;
123: password = null;
124: }
125: init0();
126: }
127:
128: /**
129: * Constructor used for proxy entries
130: */
131: public NTLMAuthentication(boolean isProxy, String host, int port,
132: PasswordAuthentication pw) {
133: super (isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
134: NTLM_AUTH, host, port, "");
135: init(pw);
136: }
137:
138: /**
139: * @return true if this authentication supports preemptive authorization
140: */
141: boolean supportsPreemptiveAuthorization() {
142: return false;
143: }
144:
145: /**
146: * @return true if NTLM supported transparently (no password needed, SSO)
147: */
148: static boolean supportsTransparentAuth() {
149: return true;
150: }
151:
152: /**
153: * @return the name of the HTTP header this authentication wants set
154: */
155: String getHeaderName() {
156: if (type == SERVER_AUTHENTICATION) {
157: return "Authorization";
158: } else {
159: return "Proxy-authorization";
160: }
161: }
162:
163: /**
164: * Not supported. Must use the setHeaders() method
165: */
166: String getHeaderValue(URL url, String method) {
167: throw new RuntimeException("getHeaderValue not supported");
168: }
169:
170: /**
171: * Check if the header indicates that the current auth. parameters are stale.
172: * If so, then replace the relevant field with the new value
173: * and return true. Otherwise return false.
174: * returning true means the request can be retried with the same userid/password
175: * returning false means we have to go back to the user to ask for a new
176: * username password.
177: */
178: boolean isAuthorizationStale(String header) {
179: return false; /* should not be called for ntlm */
180: }
181:
182: /**
183: * Set header(s) on the given connection.
184: * @param conn The connection to apply the header(s) to
185: * @param p A source of header values for this connection, not used because
186: * HeaderParser converts the fields to lower case, use raw instead
187: * @param raw The raw header field.
188: * @return true if all goes well, false if no headers were set.
189: */
190: synchronized boolean setHeaders(HttpURLConnection conn,
191: HeaderParser p, String raw) {
192:
193: try {
194: NTLMAuthSequence seq = (NTLMAuthSequence) conn.authObj;
195: if (seq == null) {
196: seq = new NTLMAuthSequence(username, password, ntdomain);
197: conn.authObj = seq;
198: }
199: String response = "NTLM "
200: + seq.getAuthHeader(raw.length() > 6 ? raw
201: .substring(5) : null);
202: conn.setAuthenticationProperty(getHeaderName(), response);
203: return true;
204: } catch (IOException e) {
205: return false;
206: }
207: }
208:
209: /* This is a no-op for NTLM, because there is no authentication information
210: * provided by the server to the client
211: */
212: public void checkResponse(String header, String method, URL url)
213: throws IOException {
214: }
215: }
|