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