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
26package java.net;
27
28import 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.
61public abstract
62class 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
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
565    protected RequestorType getRequestorType () {
566        return requestingAuthType;
567    }
568
569    static String getKey(Authenticator a) {
570        return a.key;
571    }
572    static {
573        AuthenticatorKeys.setAuthenticatorKeyAccess(Authenticator::getKey);
574    }
575}
576