View Javadoc
1   /*
2    * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.net.www.protocol.http.ntlm;
27  
28  import java.io.IOException;
29  import java.net.InetAddress;
30  import java.net.PasswordAuthentication;
31  import java.net.UnknownHostException;
32  import java.net.URL;
33  import sun.net.www.HeaderParser;
34  import sun.net.www.protocol.http.AuthenticationInfo;
35  import sun.net.www.protocol.http.AuthScheme;
36  import sun.net.www.protocol.http.HttpURLConnection;
37  
38  /**
39   * NTLMAuthentication:
40   *
41   * @author Michael McMahon
42   */
43  
44  public class NTLMAuthentication extends AuthenticationInfo {
45  
46      private static final long serialVersionUID = 100L;
47  
48      private static final NTLMAuthenticationCallback NTLMAuthCallback =
49          NTLMAuthenticationCallback.getNTLMAuthenticationCallback();
50  
51      private String hostname;
52      private static String defaultDomain; /* Domain to use if not specified by user */
53  
54      static {
55          defaultDomain = java.security.AccessController.doPrivileged(
56              new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
57                                                        "domain"));
58      };
59  
60      private void init0() {
61  
62          hostname = java.security.AccessController.doPrivileged(
63              new java.security.PrivilegedAction<String>() {
64              public String run() {
65                  String localhost;
66                  try {
67                      localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
68                  } catch (UnknownHostException e) {
69                       localhost = "localhost";
70                  }
71                  return localhost;
72              }
73          });
74          int x = hostname.indexOf ('.');
75          if (x != -1) {
76              hostname = hostname.substring (0, x);
77          }
78      }
79  
80      String username;
81      String ntdomain;
82      String password;
83  
84      /**
85       * Create a NTLMAuthentication:
86       * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
87       * If this notation is not used, then the domain will be taken
88       * from a system property: "http.auth.ntlm.domain".
89       */
90      public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
91          super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
92                AuthScheme.NTLM,
93                url,
94                "");
95          init (pw);
96      }
97  
98      private void init (PasswordAuthentication pw) {
99          this.pw = pw;
100         if (pw != null) {
101             String s = pw.getUserName();
102             int i = s.indexOf ('\\');
103             if (i == -1) {
104                 username = s;
105                 ntdomain = defaultDomain;
106             } else {
107                 ntdomain = s.substring (0, i).toUpperCase();
108                 username = s.substring (i+1);
109             }
110             password = new String (pw.getPassword());
111         } else {
112             /* credentials will be acquired from OS */
113             username = null;
114             ntdomain = null;
115             password = null;
116         }
117         init0();
118     }
119 
120    /**
121     * Constructor used for proxy entries
122     */
123     public NTLMAuthentication(boolean isProxy, String host, int port,
124                                 PasswordAuthentication pw) {
125         super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
126               AuthScheme.NTLM,
127               host,
128               port,
129               "");
130         init (pw);
131     }
132 
133     /**
134      * @return true if this authentication supports preemptive authorization
135      */
136     @Override
137     public boolean supportsPreemptiveAuthorization() {
138         return false;
139     }
140 
141     /**
142      * @return true if NTLM supported transparently (no password needed, SSO)
143      */
144     public static boolean supportsTransparentAuth() {
145         return true;
146     }
147 
148     /**
149      * Returns true if the given site is trusted, i.e. we can try
150      * transparent Authentication.
151      */
152     public static boolean isTrustedSite(URL url) {
153         return NTLMAuthCallback.isTrustedSite(url);
154     }
155 
156     /**
157      * Not supported. Must use the setHeaders() method
158      */
159     @Override
160     public String getHeaderValue(URL url, String method) {
161         throw new RuntimeException ("getHeaderValue not supported");
162     }
163 
164     /**
165      * Check if the header indicates that the current auth. parameters are stale.
166      * If so, then replace the relevant field with the new value
167      * and return true. Otherwise return false.
168      * returning true means the request can be retried with the same userid/password
169      * returning false means we have to go back to the user to ask for a new
170      * username password.
171      */
172     @Override
173     public boolean isAuthorizationStale (String header) {
174         return false; /* should not be called for ntlm */
175     }
176 
177     /**
178      * Set header(s) on the given connection.
179      * @param conn The connection to apply the header(s) to
180      * @param p A source of header values for this connection, not used because
181      *          HeaderParser converts the fields to lower case, use raw instead
182      * @param raw The raw header field.
183      * @return true if all goes well, false if no headers were set.
184      */
185     @Override
186     public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
187 
188         try {
189             NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj();
190             if (seq == null) {
191                 seq = new NTLMAuthSequence (username, password, ntdomain);
192                 conn.authObj(seq);
193             }
194             String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
195             conn.setAuthenticationProperty(getHeaderName(), response);
196             if (seq.isComplete()) {
197                 conn.authObj(null);
198             }
199             return true;
200         } catch (IOException e) {
201             conn.authObj(null);
202             return false;
203         }
204     }
205 
206 }