1 /*
   2  * Copyright (c) 1998, 2006, 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;
  27 
  28 import java.security.PrivilegedAction;
  29 import java.security.Security;
  30 
  31 public final class InetAddressCachePolicy {
  32 
  33     // Controls the cache policy for successful lookups only
  34     private static final String cachePolicyProp = "networkaddress.cache.ttl";
  35     private static final String cachePolicyPropFallback =
  36         "sun.net.inetaddr.ttl";
  37 
  38     // Controls the cache policy for negative lookups only
  39     private static final String negativeCachePolicyProp =
  40         "networkaddress.cache.negative.ttl";
  41     private static final String negativeCachePolicyPropFallback =
  42         "sun.net.inetaddr.negative.ttl";
  43 
  44     public static final int FOREVER = -1;
  45     public static final int NEVER = 0;
  46 
  47     /* default value for positive lookups */
  48     public static final int DEFAULT_POSITIVE = 30;
  49 
  50     /* The Java-level namelookup cache policy for successful lookups:
  51      *
  52      * -1: caching forever
  53      * any positive value: the number of seconds to cache an address for
  54      *
  55      * default value is forever (FOREVER), as we let the platform do the
  56      * caching. For security reasons, this caching is made forever when
  57      * a security manager is set.
  58      */
  59     private static int cachePolicy = FOREVER;
  60 
  61     /* The Java-level namelookup cache policy for negative lookups:
  62      *
  63      * -1: caching forever
  64      * any positive value: the number of seconds to cache an address for
  65      *
  66      * default value is 0. It can be set to some other value for
  67      * performance reasons.
  68      */
  69     private static int negativeCachePolicy = NEVER;
  70 
  71     /*
  72      * Whether or not the cache policy for successful lookups was set
  73      * using a property (cmd line).
  74      */
  75     private static boolean propertySet;
  76 
  77     /*
  78      * Whether or not the cache policy for negative lookups was set
  79      * using a property (cmd line).
  80      */
  81     private static boolean propertyNegativeSet;
  82 
  83     /*
  84      * Initialize
  85      */
  86     static {
  87         Integer tmp = null;
  88 
  89         try {
  90             tmp = new Integer(
  91               java.security.AccessController.doPrivileged (
  92                 new PrivilegedAction<String>() {
  93                   public String run() {
  94                       return Security.getProperty(cachePolicyProp);
  95                   }
  96               }));
  97         } catch (NumberFormatException e) {
  98             // ignore
  99         }
 100         if (tmp != null) {
 101             cachePolicy = tmp.intValue();
 102             if (cachePolicy < 0) {
 103                 cachePolicy = FOREVER;
 104             }
 105             propertySet = true;
 106         } else {
 107             tmp = java.security.AccessController.doPrivileged
 108                 (new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
 109             if (tmp != null) {
 110                 cachePolicy = tmp.intValue();
 111                 if (cachePolicy < 0) {
 112                     cachePolicy = FOREVER;
 113                 }
 114                 propertySet = true;
 115             } else {
 116                 /* No properties defined for positive caching. If there is no
 117                  * security manager then use the default positive cache value.
 118                  */
 119                 if (System.getSecurityManager() == null) {
 120                     cachePolicy = DEFAULT_POSITIVE;
 121                 }
 122             }
 123         }
 124 
 125         try {
 126             tmp = new Integer(
 127               java.security.AccessController.doPrivileged (
 128                 new PrivilegedAction<String>() {
 129                   public String run() {
 130                       return Security.getProperty(negativeCachePolicyProp);
 131                   }
 132               }));
 133         } catch (NumberFormatException e) {
 134             // ignore
 135         }
 136 
 137         if (tmp != null) {
 138             negativeCachePolicy = tmp.intValue();
 139             if (negativeCachePolicy < 0) {
 140                 negativeCachePolicy = FOREVER;
 141             }
 142             propertyNegativeSet = true;
 143         } else {
 144             tmp = java.security.AccessController.doPrivileged
 145                 (new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
 146             if (tmp != null) {
 147                 negativeCachePolicy = tmp.intValue();
 148                 if (negativeCachePolicy < 0) {
 149                     negativeCachePolicy = FOREVER;
 150                 }
 151                 propertyNegativeSet = true;
 152             }
 153         }
 154     }
 155 
 156     public static synchronized int get() {
 157         return cachePolicy;
 158     }
 159 
 160     public static synchronized int getNegative() {
 161         return negativeCachePolicy;
 162     }
 163 
 164     /**
 165      * Sets the cache policy for successful lookups if the user has not
 166      * already specified a cache policy for it using a
 167      * command-property.
 168      * @param newPolicy the value in seconds for how long the lookup
 169      * should be cached
 170      */
 171     public static synchronized void setIfNotSet(int newPolicy) {
 172         /*
 173          * When setting the new value we may want to signal that the
 174          * cache should be flushed, though this doesn't seem strictly
 175          * necessary.
 176          */
 177         if (!propertySet) {
 178             checkValue(newPolicy, cachePolicy);
 179             cachePolicy = newPolicy;
 180         }
 181     }
 182 
 183     /**
 184      * Sets the cache policy for negative lookups if the user has not
 185      * already specified a cache policy for it using a
 186      * command-property.
 187      * @param newPolicy the value in seconds for how long the lookup
 188      * should be cached
 189      */
 190     public static synchronized void setNegativeIfNotSet(int newPolicy) {
 191         /*
 192          * When setting the new value we may want to signal that the
 193          * cache should be flushed, though this doesn't seem strictly
 194          * necessary.
 195          */
 196         if (!propertyNegativeSet) {
 197             // Negative caching does not seem to have any security
 198             // implications.
 199             // checkValue(newPolicy, negativeCachePolicy);
 200             negativeCachePolicy = newPolicy;
 201         }
 202     }
 203 
 204     private static void checkValue(int newPolicy, int oldPolicy) {
 205         /*
 206          * If malicious code gets a hold of this method, prevent
 207          * setting the cache policy to something laxer or some
 208          * invalid negative value.
 209          */
 210         if (newPolicy == FOREVER)
 211             return;
 212 
 213         if ((oldPolicy == FOREVER) ||
 214             (newPolicy < oldPolicy) ||
 215             (newPolicy < FOREVER)) {
 216 
 217             throw new
 218                 SecurityException("can't make InetAddress cache more lax");
 219         }
 220     }
 221 }