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 = System.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 = System.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 
get()159     public static synchronized int get() {
160         return cachePolicy;
161     }
162 
getNegative()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      */
setIfNotSet(int newPolicy)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      */
setNegativeIfNotSet(int newPolicy)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 
checkValue(int newPolicy, int oldPolicy)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 }
225