1/*
2 * Copyright (c) 1998, 2014, 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 sun.net;
27
28import java.security.PrivilegedAction;
29import java.security.Security;
30
31public 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 volatile 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 volatile 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 < 0 ? FOREVER : tmp;
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        tmp = java.security.AccessController.doPrivileged (
124          new PrivilegedAction<Integer>() {
125            public Integer run() {
126                try {
127                    String tmpString = Security.getProperty(negativeCachePolicyProp);
128                    if (tmpString != null) {
129                        return Integer.valueOf(tmpString);
130                    }
131                } catch (NumberFormatException ignored) {
132                    // Ignore
133                }
134
135                try {
136                    String tmpString = System.getProperty(negativeCachePolicyPropFallback);
137                    if (tmpString != null) {
138                        return Integer.decode(tmpString);
139                    }
140                } catch (NumberFormatException ignored) {
141                    // Ignore
142                }
143                return null;
144            }
145          });
146
147        if (tmp != null) {
148            negativeCachePolicy = tmp < 0 ? FOREVER : tmp;
149            propertyNegativeSet = true;
150        }
151    }
152
153    public static int get() {
154        return cachePolicy;
155    }
156
157    public static int getNegative() {
158        return negativeCachePolicy;
159    }
160
161    /**
162     * Sets the cache policy for successful lookups if the user has not
163     * already specified a cache policy for it using a
164     * command-property.
165     * @param newPolicy the value in seconds for how long the lookup
166     * should be cached
167     */
168    public static synchronized void setIfNotSet(int newPolicy) {
169        /*
170         * When setting the new value we may want to signal that the
171         * cache should be flushed, though this doesn't seem strictly
172         * necessary.
173         */
174        if (!propertySet) {
175            checkValue(newPolicy, cachePolicy);
176            cachePolicy = newPolicy;
177        }
178    }
179
180    /**
181     * Sets the cache policy for negative lookups if the user has not
182     * already specified a cache policy for it using a
183     * command-property.
184     * @param newPolicy the value in seconds for how long the lookup
185     * should be cached
186     */
187    public static void setNegativeIfNotSet(int newPolicy) {
188        /*
189         * When setting the new value we may want to signal that the
190         * cache should be flushed, though this doesn't seem strictly
191         * necessary.
192         */
193        if (!propertyNegativeSet) {
194            // Negative caching does not seem to have any security
195            // implications.
196            // checkValue(newPolicy, negativeCachePolicy);
197            // but we should normalize negative policy
198            negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy;
199        }
200    }
201
202    private static void checkValue(int newPolicy, int oldPolicy) {
203        /*
204         * If malicious code gets a hold of this method, prevent
205         * setting the cache policy to something laxer or some
206         * invalid negative value.
207         */
208        if (newPolicy == FOREVER)
209            return;
210
211        if ((oldPolicy == FOREVER) ||
212            (newPolicy < oldPolicy) ||
213            (newPolicy < FOREVER)) {
214
215            throw new
216                SecurityException("can't make InetAddress cache more lax");
217        }
218    }
219}
220