1 /*
   2  * Copyright (c) 1998, 2010, 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 
  88         Integer tmp = java.security.AccessController.doPrivileged(
  89           new PrivilegedAction<Integer>() {
  90             public Integer run() {
  91                 try {
  92                     String tmpString = Security.getProperty(cachePolicyProp);
  93                     if (tmpString != null) {
  94                         return Integer.valueOf(tmpString);
  95                     }
  96                 } catch (NumberFormatException ignored) {
  97                     // Ignore
  98                 }
  99 
 100                 try {
 101                     String tmpString = Security.getProperty(cachePolicyPropFallback);
 102                     if (tmpString != null) {
 103                         return Integer.decode(tmpString);
 104                     }
 105                 } catch (NumberFormatException ignored) {
 106                     // Ignore
 107                 }
 108                 return null;
 109             }
 110           });
 111 
 112         if (tmp != null) {
 113             cachePolicy = tmp.intValue();
 114             if (cachePolicy < 0) {
 115                 cachePolicy = FOREVER;
 116             }
 117             propertySet = true;
 118         } else {
 119             /* No properties defined for positive caching. If there is no
 120              * security manager then use the default positive cache value.
 121              */
 122             if (System.getSecurityManager() == null) {
 123                 cachePolicy = DEFAULT_POSITIVE;
 124             }
 125         }
 126         tmp = java.security.AccessController.doPrivileged (
 127           new PrivilegedAction<Integer>() {
 128             public Integer run() {
 129                 try {
 130                     String tmpString = Security.getProperty(negativeCachePolicyProp);
 131                     if (tmpString != null) {
 132                         return Integer.valueOf(tmpString);
 133                     }
 134                 } catch (NumberFormatException ignored) {
 135                     // Ignore
 136                 }
 137 
 138                 try {
 139                     String tmpString = Security.getProperty(negativeCachePolicyPropFallback);
 140                     if (tmpString != null) {
 141                         return Integer.decode(tmpString);
 142                     }
 143                 } catch (NumberFormatException ignored) {
 144                     // Ignore
 145                 }
 146                 return null;
 147             }
 148           });
 149 
 150         if (tmp != null) {
 151             negativeCachePolicy = tmp.intValue();
 152             if (negativeCachePolicy < 0) {
 153                 negativeCachePolicy = FOREVER;
 154             }
 155             propertyNegativeSet = true;
 156         }
 157     }
 158 
 159     public static synchronized int get() {
 160         return cachePolicy;
 161     }
 162 
 163     public static synchronized int getNegative() {
 164         return negativeCachePolicy;
 165     }
 166 
 167     /**
 168      * Sets the cache policy for successful lookups if the user has not
 169      * already specified a cache policy for it using a
 170      * command-property.
 171      * @param newPolicy the value in seconds for how long the lookup
 172      * should be cached
 173      */
 174     public static synchronized void setIfNotSet(int newPolicy) {
 175         /*
 176          * When setting the new value we may want to signal that the
 177          * cache should be flushed, though this doesn't seem strictly
 178          * necessary.
 179          */
 180         if (!propertySet) {
 181             checkValue(newPolicy, cachePolicy);
 182             cachePolicy = newPolicy;
 183         }
 184     }
 185 
 186     /**
 187      * Sets the cache policy for negative lookups if the user has not
 188      * already specified a cache policy for it using a
 189      * command-property.
 190      * @param newPolicy the value in seconds for how long the lookup
 191      * should be cached
 192      */
 193     public static synchronized void setNegativeIfNotSet(int newPolicy) {
 194         /*
 195          * When setting the new value we may want to signal that the
 196          * cache should be flushed, though this doesn't seem strictly
 197          * necessary.
 198          */
 199         if (!propertyNegativeSet) {
 200             // Negative caching does not seem to have any security
 201             // implications.
 202             // checkValue(newPolicy, negativeCachePolicy);
 203             negativeCachePolicy = newPolicy;
 204         }
 205     }
 206 
 207     private static void checkValue(int newPolicy, int oldPolicy) {
 208         /*
 209          * If malicious code gets a hold of this method, prevent
 210          * setting the cache policy to something laxer or some
 211          * invalid negative value.
 212          */
 213         if (newPolicy == FOREVER)
 214             return;
 215 
 216         if ((oldPolicy == FOREVER) ||
 217             (newPolicy < oldPolicy) ||
 218             (newPolicy < FOREVER)) {
 219 
 220             throw new
 221                 SecurityException("can't make InetAddress cache more lax");
 222         }
 223     }
 224 }