1 /*
2  * Copyright (c) 1997, 2016, 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 java.net;
27 
28 import sun.net.www.protocol.http.AuthenticatorKeys;
29 
30 /**
31  * The class Authenticator represents an object that knows how to obtain
32  * authentication for a network connection.  Usually, it will do this
33  * by prompting the user for information.
34  * <p>
35  * Applications use this class by overriding {@link
36  * #getPasswordAuthentication()} in a sub-class. This method will
37  * typically use the various getXXX() accessor methods to get information
38  * about the entity requesting authentication. It must then acquire a
39  * username and password either by interacting with the user or through
40  * some other non-interactive means. The credentials are then returned
41  * as a {@link PasswordAuthentication} return value.
42  * <p>
43  * An instance of this concrete sub-class is then registered
44  * with the system by calling {@link #setDefault(Authenticator)}.
45  * When authentication is required, the system will invoke one of the
46  * requestPasswordAuthentication() methods which in turn will call the
47  * getPasswordAuthentication() method of the registered object.
48  * <p>
49  * All methods that request authentication have a default implementation
50  * that fails.
51  *
52  * @see java.net.Authenticator#setDefault(java.net.Authenticator)
53  * @see java.net.Authenticator#getPasswordAuthentication()
54  *
55  * @author  Bill Foote
56  * @since   1.2
57  */
58 
59 // There are no abstract methods, but to be useful the user must
60 // subclass.
61 public abstract
62 class Authenticator {
63 
64     // The system-wide authenticator object.  See setDefault().
65     private static volatile Authenticator theAuthenticator;
66 
67     private String requestingHost;
68     private InetAddress requestingSite;
69     private int requestingPort;
70     private String requestingProtocol;
71     private String requestingPrompt;
72     private String requestingScheme;
73     private URL requestingURL;
74     private RequestorType requestingAuthType;
75     private final String key = AuthenticatorKeys.computeKey(this);
76 
77     /**
78      * The type of the entity requesting authentication.
79      *
80      * @since 1.5
81      */
82     public enum RequestorType {
83         /**
84          * Entity requesting authentication is a HTTP proxy server.
85          */
86         PROXY,
87         /**
88          * Entity requesting authentication is a HTTP origin server.
89          */
90         SERVER
91     }
92 
reset()93     private void reset() {
94         requestingHost = null;
95         requestingSite = null;
96         requestingPort = -1;
97         requestingProtocol = null;
98         requestingPrompt = null;
99         requestingScheme = null;
100         requestingURL = null;
101         requestingAuthType = RequestorType.SERVER;
102     }
103 
104 
105     /**
106      * Sets the authenticator that will be used by the networking code
107      * when a proxy or an HTTP server asks for authentication.
108      * <p>
109      * First, if there is a security manager, its {@code checkPermission}
110      * method is called with a
111      * {@code NetPermission("setDefaultAuthenticator")} permission.
112      * This may result in a java.lang.SecurityException.
113      *
114      * @param   a       The authenticator to be set. If a is {@code null} then
115      *                  any previously set authenticator is removed.
116      *
117      * @throws SecurityException
118      *        if a security manager exists and its
119      *        {@code checkPermission} method doesn't allow
120      *        setting the default authenticator.
121      *
122      * @see SecurityManager#checkPermission
123      * @see java.net.NetPermission
124      */
setDefault(Authenticator a)125     public static synchronized void setDefault(Authenticator a) {
126         SecurityManager sm = System.getSecurityManager();
127         if (sm != null) {
128             NetPermission setDefaultPermission
129                 = new NetPermission("setDefaultAuthenticator");
130             sm.checkPermission(setDefaultPermission);
131         }
132 
133         theAuthenticator = a;
134     }
135 
136     /**
137      * Gets the default authenticator.
138      * First, if there is a security manager, its {@code checkPermission}
139      * method is called with a
140      * {@code NetPermission("requestPasswordAuthentication")} permission.
141      * This may result in a java.lang.SecurityException.
142      * Then the default authenticator, if set, is returned.
143      * Otherwise, {@code null} is returned.
144      *
145      * @return The default authenticator, if set, {@code null} otherwise.
146      *
147      * @throws SecurityException
148      *        if a security manager exists and its
149      *        {@code checkPermission} method doesn't allow
150      *        requesting password authentication.
151      * @since 9
152      * @see SecurityManager#checkPermission
153      * @see java.net.NetPermission
154      */
getDefault()155     public static Authenticator getDefault() {
156         SecurityManager sm = System.getSecurityManager();
157         if (sm != null) {
158             NetPermission requestPermission
159                 = new NetPermission("requestPasswordAuthentication");
160             sm.checkPermission(requestPermission);
161         }
162         return theAuthenticator;
163     }
164 
165     /**
166      * Ask the authenticator that has been registered with the system
167      * for a password.
168      * <p>
169      * First, if there is a security manager, its {@code checkPermission}
170      * method is called with a
171      * {@code NetPermission("requestPasswordAuthentication")} permission.
172      * This may result in a java.lang.SecurityException.
173      *
174      * @param addr The InetAddress of the site requesting authorization,
175      *             or null if not known.
176      * @param port the port for the requested connection
177      * @param protocol The protocol that's requesting the connection
178      *          ({@link java.net.Authenticator#getRequestingProtocol()})
179      * @param prompt A prompt string for the user
180      * @param scheme The authentication scheme
181      *
182      * @return The username/password, or null if one can't be gotten.
183      *
184      * @throws SecurityException
185      *        if a security manager exists and its
186      *        {@code checkPermission} method doesn't allow
187      *        the password authentication request.
188      *
189      * @see SecurityManager#checkPermission
190      * @see java.net.NetPermission
191      */
requestPasswordAuthentication( InetAddress addr, int port, String protocol, String prompt, String scheme)192     public static PasswordAuthentication requestPasswordAuthentication(
193                                             InetAddress addr,
194                                             int port,
195                                             String protocol,
196                                             String prompt,
197                                             String scheme) {
198 
199         SecurityManager sm = System.getSecurityManager();
200         if (sm != null) {
201             NetPermission requestPermission
202                 = new NetPermission("requestPasswordAuthentication");
203             sm.checkPermission(requestPermission);
204         }
205 
206         Authenticator a = theAuthenticator;
207         if (a == null) {
208             return null;
209         } else {
210             synchronized(a) {
211                 a.reset();
212                 a.requestingSite = addr;
213                 a.requestingPort = port;
214                 a.requestingProtocol = protocol;
215                 a.requestingPrompt = prompt;
216                 a.requestingScheme = scheme;
217                 return a.getPasswordAuthentication();
218             }
219         }
220     }
221 
222     /**
223      * Ask the authenticator that has been registered with the system
224      * for a password. This is the preferred method for requesting a password
225      * because the hostname can be provided in cases where the InetAddress
226      * is not available.
227      * <p>
228      * First, if there is a security manager, its {@code checkPermission}
229      * method is called with a
230      * {@code NetPermission("requestPasswordAuthentication")} permission.
231      * This may result in a java.lang.SecurityException.
232      *
233      * @param host The hostname of the site requesting authentication.
234      * @param addr The InetAddress of the site requesting authentication,
235      *             or null if not known.
236      * @param port the port for the requested connection.
237      * @param protocol The protocol that's requesting the connection
238      *          ({@link java.net.Authenticator#getRequestingProtocol()})
239      * @param prompt A prompt string for the user which identifies the authentication realm.
240      * @param scheme The authentication scheme
241      *
242      * @return The username/password, or null if one can't be gotten.
243      *
244      * @throws SecurityException
245      *        if a security manager exists and its
246      *        {@code checkPermission} method doesn't allow
247      *        the password authentication request.
248      *
249      * @see SecurityManager#checkPermission
250      * @see java.net.NetPermission
251      * @since 1.4
252      */
requestPasswordAuthentication( String host, InetAddress addr, int port, String protocol, String prompt, String scheme)253     public static PasswordAuthentication requestPasswordAuthentication(
254                                             String host,
255                                             InetAddress addr,
256                                             int port,
257                                             String protocol,
258                                             String prompt,
259                                             String scheme) {
260 
261         SecurityManager sm = System.getSecurityManager();
262         if (sm != null) {
263             NetPermission requestPermission
264                 = new NetPermission("requestPasswordAuthentication");
265             sm.checkPermission(requestPermission);
266         }
267 
268         Authenticator a = theAuthenticator;
269         if (a == null) {
270             return null;
271         } else {
272             synchronized(a) {
273                 a.reset();
274                 a.requestingHost = host;
275                 a.requestingSite = addr;
276                 a.requestingPort = port;
277                 a.requestingProtocol = protocol;
278                 a.requestingPrompt = prompt;
279                 a.requestingScheme = scheme;
280                 return a.getPasswordAuthentication();
281             }
282         }
283     }
284 
285     /**
286      * Ask the authenticator that has been registered with the system
287      * for a password.
288      * <p>
289      * First, if there is a security manager, its {@code checkPermission}
290      * method is called with a
291      * {@code NetPermission("requestPasswordAuthentication")} permission.
292      * This may result in a java.lang.SecurityException.
293      *
294      * @param host The hostname of the site requesting authentication.
295      * @param addr The InetAddress of the site requesting authorization,
296      *             or null if not known.
297      * @param port the port for the requested connection
298      * @param protocol The protocol that's requesting the connection
299      *          ({@link java.net.Authenticator#getRequestingProtocol()})
300      * @param prompt A prompt string for the user
301      * @param scheme The authentication scheme
302      * @param url The requesting URL that caused the authentication
303      * @param reqType The type (server or proxy) of the entity requesting
304      *              authentication.
305      *
306      * @return The username/password, or null if one can't be gotten.
307      *
308      * @throws SecurityException
309      *        if a security manager exists and its
310      *        {@code checkPermission} method doesn't allow
311      *        the password authentication request.
312      *
313      * @see SecurityManager#checkPermission
314      * @see java.net.NetPermission
315      *
316      * @since 1.5
317      */
requestPasswordAuthentication( String host, InetAddress addr, int port, String protocol, String prompt, String scheme, URL url, RequestorType reqType)318     public static PasswordAuthentication requestPasswordAuthentication(
319                                     String host,
320                                     InetAddress addr,
321                                     int port,
322                                     String protocol,
323                                     String prompt,
324                                     String scheme,
325                                     URL url,
326                                     RequestorType reqType) {
327 
328         SecurityManager sm = System.getSecurityManager();
329         if (sm != null) {
330             NetPermission requestPermission
331                 = new NetPermission("requestPasswordAuthentication");
332             sm.checkPermission(requestPermission);
333         }
334 
335         Authenticator a = theAuthenticator;
336         if (a == null) {
337             return null;
338         } else {
339             synchronized(a) {
340                 a.reset();
341                 a.requestingHost = host;
342                 a.requestingSite = addr;
343                 a.requestingPort = port;
344                 a.requestingProtocol = protocol;
345                 a.requestingPrompt = prompt;
346                 a.requestingScheme = scheme;
347                 a.requestingURL = url;
348                 a.requestingAuthType = reqType;
349                 return a.getPasswordAuthentication();
350             }
351         }
352     }
353 
354     /**
355      * Ask the given {@code authenticator} for a password. If the given
356      * {@code authenticator} is null, the authenticator, if any, that has been
357      * registered with the system using {@link #setDefault(java.net.Authenticator)
358      * setDefault} is used.
359      * <p>
360      * First, if there is a security manager, its {@code checkPermission}
361      * method is called with a
362      * {@code NetPermission("requestPasswordAuthentication")} permission.
363      * This may result in a java.lang.SecurityException.
364      *
365      * @param authenticator the authenticator, or {@code null}.
366      * @param host The hostname of the site requesting authentication.
367      * @param addr The InetAddress of the site requesting authorization,
368      *             or null if not known.
369      * @param port the port for the requested connection
370      * @param protocol The protocol that's requesting the connection
371      *          ({@link java.net.Authenticator#getRequestingProtocol()})
372      * @param prompt A prompt string for the user
373      * @param scheme The authentication scheme
374      * @param url The requesting URL that caused the authentication
375      * @param reqType The type (server or proxy) of the entity requesting
376      *              authentication.
377      *
378      * @return The username/password, or {@code null} if one can't be gotten.
379      *
380      * @throws SecurityException
381      *        if a security manager exists and its
382      *        {@code checkPermission} method doesn't allow
383      *        the password authentication request.
384      *
385      * @see SecurityManager#checkPermission
386      * @see java.net.NetPermission
387      *
388      * @since 9
389      */
requestPasswordAuthentication( Authenticator authenticator, String host, InetAddress addr, int port, String protocol, String prompt, String scheme, URL url, RequestorType reqType)390     public static PasswordAuthentication requestPasswordAuthentication(
391                                     Authenticator authenticator,
392                                     String host,
393                                     InetAddress addr,
394                                     int port,
395                                     String protocol,
396                                     String prompt,
397                                     String scheme,
398                                     URL url,
399                                     RequestorType reqType) {
400 
401         SecurityManager sm = System.getSecurityManager();
402         if (sm != null) {
403             NetPermission requestPermission
404                 = new NetPermission("requestPasswordAuthentication");
405             sm.checkPermission(requestPermission);
406         }
407 
408         Authenticator a = authenticator == null ? theAuthenticator : authenticator;
409         if (a == null) {
410             return null;
411         } else {
412             return a.requestPasswordAuthenticationInstance(host,
413                                                            addr,
414                                                            port,
415                                                            protocol,
416                                                            prompt,
417                                                            scheme,
418                                                            url,
419                                                            reqType);
420         }
421     }
422 
423     /**
424      * Ask this authenticator for a password.
425      *
426      * @param host The hostname of the site requesting authentication.
427      * @param addr The InetAddress of the site requesting authorization,
428      *             or null if not known.
429      * @param port the port for the requested connection
430      * @param protocol The protocol that's requesting the connection
431      *          ({@link java.net.Authenticator#getRequestingProtocol()})
432      * @param prompt A prompt string for the user
433      * @param scheme The authentication scheme
434      * @param url The requesting URL that caused the authentication
435      * @param reqType The type (server or proxy) of the entity requesting
436      *              authentication.
437      *
438      * @return The username/password, or null if one can't be gotten
439      *
440      * @since 9
441      */
442     public PasswordAuthentication
requestPasswordAuthenticationInstance(String host, InetAddress addr, int port, String protocol, String prompt, String scheme, URL url, RequestorType reqType)443     requestPasswordAuthenticationInstance(String host,
444                                           InetAddress addr,
445                                           int port,
446                                           String protocol,
447                                           String prompt,
448                                           String scheme,
449                                           URL url,
450                                           RequestorType reqType) {
451         synchronized (this) {
452             this.reset();
453             this.requestingHost = host;
454             this.requestingSite = addr;
455             this.requestingPort = port;
456             this.requestingProtocol = protocol;
457             this.requestingPrompt = prompt;
458             this.requestingScheme = scheme;
459             this.requestingURL = url;
460             this.requestingAuthType = reqType;
461             return this.getPasswordAuthentication();
462         }
463     }
464 
465     /**
466      * Gets the {@code hostname} of the
467      * site or proxy requesting authentication, or {@code null}
468      * if not available.
469      *
470      * @return the hostname of the connection requiring authentication, or null
471      *          if it's not available.
472      * @since 1.4
473      */
getRequestingHost()474     protected final String getRequestingHost() {
475         return requestingHost;
476     }
477 
478     /**
479      * Gets the {@code InetAddress} of the
480      * site requesting authorization, or {@code null}
481      * if not available.
482      *
483      * @return the InetAddress of the site requesting authorization, or null
484      *          if it's not available.
485      */
getRequestingSite()486     protected final InetAddress getRequestingSite() {
487         return requestingSite;
488     }
489 
490     /**
491      * Gets the port number for the requested connection.
492      * @return an {@code int} indicating the
493      * port for the requested connection.
494      */
getRequestingPort()495     protected final int getRequestingPort() {
496         return requestingPort;
497     }
498 
499     /**
500      * Give the protocol that's requesting the connection.  Often this
501      * will be based on a URL, but in a future JDK it could be, for
502      * example, "SOCKS" for a password-protected SOCKS5 firewall.
503      *
504      * @return the protocol, optionally followed by "/version", where
505      *          version is a version number.
506      *
507      * @see java.net.URL#getProtocol()
508      */
getRequestingProtocol()509     protected final String getRequestingProtocol() {
510         return requestingProtocol;
511     }
512 
513     /**
514      * Gets the prompt string given by the requestor.
515      *
516      * @return the prompt string given by the requestor (realm for
517      *          http requests)
518      */
getRequestingPrompt()519     protected final String getRequestingPrompt() {
520         return requestingPrompt;
521     }
522 
523     /**
524      * Gets the scheme of the requestor (the HTTP scheme
525      * for an HTTP firewall, for example).
526      *
527      * @return the scheme of the requestor
528      *
529      */
getRequestingScheme()530     protected final String getRequestingScheme() {
531         return requestingScheme;
532     }
533 
534     /**
535      * Called when password authorization is needed.  Subclasses should
536      * override the default implementation, which returns null.
537      * @return The PasswordAuthentication collected from the
538      *          user, or null if none is provided.
539      */
getPasswordAuthentication()540     protected PasswordAuthentication getPasswordAuthentication() {
541         return null;
542     }
543 
544     /**
545      * Returns the URL that resulted in this
546      * request for authentication.
547      *
548      * @since 1.5
549      *
550      * @return the requesting URL
551      *
552      */
getRequestingURL()553     protected URL getRequestingURL () {
554         return requestingURL;
555     }
556 
557     /**
558      * Returns whether the requestor is a Proxy or a Server.
559      *
560      * @since 1.5
561      *
562      * @return the authentication type of the requestor
563      *
564      */
getRequestorType()565     protected RequestorType getRequestorType () {
566         return requestingAuthType;
567     }
568 
getKey(Authenticator a)569     static String getKey(Authenticator a) {
570         return a.key;
571     }
572     static {
573         AuthenticatorKeys.setAuthenticatorKeyAccess(Authenticator::getKey);
574     }
575 }
576