1/*
2 * Copyright (c) 2013, 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 com.sun.org.apache.xerces.internal.utils;
27
28import com.sun.org.apache.xerces.internal.impl.Constants;
29import javax.xml.XMLConstants;
30
31/**
32 * This class manages security related properties
33 *
34 */
35public final class XMLSecurityPropertyManager {
36
37    /**
38     * States of the settings of a property, in the order: default value, value
39     * set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system
40     * properties, and jaxp api properties
41     */
42    public static enum State {
43        //this order reflects the overriding order
44        DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY
45    }
46
47    /**
48     * Limits managed by the security manager
49     */
50    public static enum Property {
51        ACCESS_EXTERNAL_DTD(XMLConstants.ACCESS_EXTERNAL_DTD,
52                Constants.EXTERNAL_ACCESS_DEFAULT),
53        ACCESS_EXTERNAL_SCHEMA(XMLConstants.ACCESS_EXTERNAL_SCHEMA,
54                Constants.EXTERNAL_ACCESS_DEFAULT);
55
56        final String name;
57        final String defaultValue;
58
59        Property(String name, String value) {
60            this.name = name;
61            this.defaultValue = value;
62        }
63
64        public boolean equalsName(String propertyName) {
65            return (propertyName == null) ? false : name.equals(propertyName);
66        }
67
68        String defaultValue() {
69            return defaultValue;
70        }
71    }
72
73    /**
74     * Values of the properties as defined in enum Properties
75     */
76    private final String[] values;
77    /**
78     * States of the settings for each property in Properties above
79     */
80    private State[] states = {State.DEFAULT, State.DEFAULT};
81
82    /**
83     * Default constructor. Establishes default values
84     */
85    public XMLSecurityPropertyManager() {
86        values = new String[Property.values().length];
87        for (Property property : Property.values()) {
88            values[property.ordinal()] = property.defaultValue();
89        }
90        //read system properties or jaxp.properties
91        readSystemProperties();
92    }
93
94
95    /**
96     * Set limit by property name and state
97     * @param propertyName property name
98     * @param state the state of the property
99     * @param value the value of the property
100     * @return true if the property is managed by the security property manager;
101     *         false if otherwise.
102     */
103    public boolean setValue(String propertyName, State state, Object value) {
104        int index = getIndex(propertyName);
105        if (index > -1) {
106            setValue(index, state, (String)value);
107            return true;
108        }
109        return false;
110    }
111
112    /**
113     * Set the value for a specific property.
114     *
115     * @param property the property
116     * @param state the state of the property
117     * @param value the value of the property
118     */
119    public void setValue(Property property, State state, String value) {
120        //only update if it shall override
121        if (state.compareTo(states[property.ordinal()]) >= 0) {
122            values[property.ordinal()] = value;
123            states[property.ordinal()] = state;
124        }
125    }
126
127    /**
128     * Set the value of a property by its index
129     * @param index the index of the property
130     * @param state the state of the property
131     * @param value the value of the property
132     */
133    public void setValue(int index, State state, String value) {
134        //only update if it shall override
135        if (state.compareTo(states[index]) >= 0) {
136            values[index] = value;
137            states[index] = state;
138        }
139    }
140
141
142    /**
143     * Return the value of the specified property
144     *
145     * @param propertyName the property name
146     * @return the value of the property as a string
147     */
148    public String getValue(String propertyName) {
149        int index = getIndex(propertyName);
150        if (index > -1) {
151            return getValueByIndex(index);
152        }
153
154        return null;
155    }
156
157    /**
158     * Return the value of the specified property
159     *
160     * @param property the property
161     * @return the value of the property
162     */
163    public String getValue(Property property) {
164        return values[property.ordinal()];
165    }
166
167    /**
168     * Return the value of a property by its ordinal
169     * @param index the index of a property
170     * @return value of a property
171     */
172    public String getValueByIndex(int index) {
173        return values[index];
174    }
175
176    /**
177     * Get the index by property name
178     * @param propertyName property name
179     * @return the index of the property if found; return -1 if not
180     */
181    public int getIndex(String propertyName){
182        for (Property property : Property.values()) {
183            if (property.equalsName(propertyName)) {
184                //internally, ordinal is used as index
185                return property.ordinal();
186            }
187        }
188        return -1;
189    }
190
191    /**
192     * Read from system properties, or those in jaxp.properties
193     */
194    private void readSystemProperties() {
195        getSystemProperty(Property.ACCESS_EXTERNAL_DTD,
196                Constants.SP_ACCESS_EXTERNAL_DTD);
197        getSystemProperty(Property.ACCESS_EXTERNAL_SCHEMA,
198                Constants.SP_ACCESS_EXTERNAL_SCHEMA);
199    }
200
201    /**
202     * Read from system properties, or those in jaxp.properties
203     *
204     * @param property the property
205     * @param systemProperty the name of the system property
206     */
207    private void getSystemProperty(Property property, String systemProperty) {
208        try {
209            String value = SecuritySupport.getSystemProperty(systemProperty);
210            if (value != null) {
211                values[property.ordinal()] = value;
212                states[property.ordinal()] = State.SYSTEMPROPERTY;
213                return;
214            }
215
216            value = SecuritySupport.readJAXPProperty(systemProperty);
217            if (value != null) {
218                values[property.ordinal()] = value;
219                states[property.ordinal()] = State.JAXPDOTPROPERTIES;
220            }
221        } catch (NumberFormatException e) {
222            //invalid setting ignored
223        }
224    }
225}
226