1 /*Copyright (C) 2014 Red Hat, Inc.
2 
3 This file is part of IcedTea.
4 
5 IcedTea is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 2.
8 
9 IcedTea is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with IcedTea; see the file COPYING.  If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301 USA.
18 
19 Linking this library statically or dynamically with other modules is
20 making a combined work based on this library.  Thus, the terms and
21 conditions of the GNU General Public License cover the whole
22 combination.
23 
24 As a special exception, the copyright holders of this library give you
25 permission to link this library with independent modules to produce an
26 executable, regardless of the license terms of these independent
27 modules, and to copy and distribute the resulting executable under
28 terms of your choice, provided that you also meet, for each linked
29 independent module, the terms and conditions of the license of that
30 module.  An independent module is a module which is not derived from
31 or based on this library.  If you modify this library, you may extend
32 this exception to your version of the library, but you are not
33 obligated to do so.  If you do not wish to do so, delete this
34 exception statement from your version.
35  */
36 
37 package net.sourceforge.jnlp.security.policyeditor;
38 
39 import net.sourceforge.jnlp.util.FileUtils;
40 import org.junit.Before;
41 import org.junit.Test;
42 
43 import java.io.File;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.Map;
49 import java.util.Set;
50 
51 import static org.junit.Assert.*;
52 import static org.junit.Assert.assertEquals;
53 
54 public class PolicyEditorControllerTest {
55 
56     private String tempFilePath;
57     private PolicyEditorController controller;
58 
59     @Before
setNewTempfile()60     public void setNewTempfile() throws Exception {
61         tempFilePath = File.createTempFile("policyeditor", null).getCanonicalPath();
62         controller = new PolicyEditorController();
63         controller.setFile(new File(tempFilePath));
64     }
65 
66     @Test
testChangesMadeInitiallyFalse()67     public void testChangesMadeInitiallyFalse() throws Exception {
68         // #setFile() counts as a change made
69         assertTrue("Controller should report changes made initially", controller.changesMade());
70     }
71 
72     @Test
testChangesMade()73     public void testChangesMade() throws Exception {
74         controller.setChangesMade(false);
75         assertFalse("Controller should have changes made marked false after being explicitly set", controller.changesMade());
76     }
77 
78     @Test
testFileHasChanged()79     public void testFileHasChanged() throws Exception {
80         assertFalse("File should not have been changed initially", controller.fileHasChanged());
81     }
82 
83     @Test
testFileHasChangedWithChange()84     public void testFileHasChangedWithChange() throws Exception {
85         assertFalse("Controller should report file has changed initially", controller.fileHasChanged());
86         final String codebase = "http://example.com";
87         final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD;
88         final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions);
89         final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL);
90         final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission);
91         final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions);
92         FileUtils.saveFile(policyEntry.toString(), new File(tempFilePath));
93         controller.openAndParsePolicyFile();
94         final Collection<PolicyEditorPermissions> editorPermissions2 = Collections.singleton(PolicyEditorPermissions.ALL_AWT);
95         final PolicyEntry policyEntry2 = new PolicyEntry(codebase, editorPermissions2, customPermissions);
96         FileUtils.saveFile(policyEntry2.toString(), new File(tempFilePath));
97         assertTrue("File should be marked changed after being externally modified", controller.fileHasChanged());
98     }
99 
100     @Test
testInitialCodebase()101     public void testInitialCodebase() throws Exception {
102         final Collection<String> initialCodebases = controller.getCodebases();
103         assertEquals("Controller should have no codebases to begin with", 0, initialCodebases.size());
104     }
105 
106     @Test
testAddCodebase()107     public void testAddCodebase() throws Exception {
108         final String urlString = "http://example.com";
109         controller.addCodebase(urlString);
110         final Collection<String> codebases = controller.getCodebases();
111         assertTrue("Controller should have http://example.com", codebases.contains(urlString));
112         assertEquals("Controller should only have two codebases", 1, codebases.size());
113     }
114 
115     @Test
testAddMultipleCodebases()116     public void testAddMultipleCodebases() throws Exception {
117         final Set<String> toAdd = new HashSet<String>();
118         toAdd.add("http://example.com");
119         toAdd.add("http://icedtea.classpath.org");
120         for (final String cb : toAdd) {
121             controller.addCodebase(cb);
122         }
123         final Collection<String> codebases = controller.getCodebases();
124         for (final String codebase : toAdd) {
125             assertTrue("Controller should have " + codebase, codebases.contains(codebase));
126         }
127     }
128 
129     @Test
testRemoveCodebase()130     public void testRemoveCodebase() throws Exception {
131         final String urlString = "http://example.com";
132         controller.addCodebase(urlString);
133         final Collection<String> codebases = controller.getCodebases();
134         assertTrue("Controller should have http://example.com", codebases.contains(urlString));
135         assertEquals("Controller should only have one codebase", 1, codebases.size());
136         controller.removeCodebase(urlString);
137         final Collection<String> afterRemove = controller.getCodebases();
138         assertFalse("Controller should not have http://example.com. Contained: " + afterRemove, afterRemove.contains(urlString));
139         assertEquals("Controller should have no codebases", 0, afterRemove.size());
140     }
141 
142     @Test
testCopyPasteCodebase()143     public void testCopyPasteCodebase() throws Exception {
144         final String copyUrl = "http://example.com";
145         final String pasteUrl = "http://example.com/example";
146         final PolicyEditorPermissions clipBoard = PolicyEditorPermissions.CLIPBOARD;
147         controller.addCodebase(copyUrl);
148         controller.setPermission(copyUrl, clipBoard, Boolean.TRUE);
149         final Collection<String> beforePasteCodebases = controller.getCodebases();
150         assertTrue("Controller should contain original codebase: " + copyUrl, beforePasteCodebases.contains(copyUrl));
151         assertTrue(copyUrl + " should have " + clipBoard, controller.getPermissions(copyUrl).get(clipBoard));
152         controller.copyCodebaseToClipboard(copyUrl);
153         final PolicyEntry clipboardEntry = PolicyEditorController.getPolicyEntryFromClipboard();
154         controller.addPolicyEntry(new PolicyEntry(pasteUrl, clipboardEntry.getPermissions(), clipboardEntry.getCustomPermissions()));
155         final Collection<String> afterPasteCodebases = controller.getCodebases();
156         assertTrue("Controller should still contain original codebase: " + copyUrl, afterPasteCodebases.contains(copyUrl));
157         assertTrue("Controller should also contain pasted codebase:" + pasteUrl, afterPasteCodebases.contains(pasteUrl));
158         assertTrue(copyUrl + " should have " + clipBoard, controller.getPermissions(copyUrl).get(clipBoard));
159         assertTrue(pasteUrl + " should have " + clipBoard, controller.getPermissions(pasteUrl).get(clipBoard));
160     }
161 
162     @Test
testAddPolicyEntry()163     public void testAddPolicyEntry() throws Exception {
164         final String codebase = "http://example.com";
165         final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD;
166         final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions);
167         final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL);
168         final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission);
169         final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions);
170         controller.addPolicyEntry(policyEntry);
171         final Collection<String> codebases = controller.getCodebases();
172         assertTrue("Controller should have " + codebase, codebases.contains(codebase));
173         assertEquals("Controller should only have one codebase", 1, codebases.size());
174         assertTrue("Controller should have granted " + editorPermissions, controller.getPermission(codebase, editorPermissions));
175         assertTrue("Controller should have granted " + customPermission, controller.getCustomPermissions(codebase).contains(customPermission));
176     }
177 
178     @Test
testAddCustomPermissionNoActions()179     public void testAddCustomPermissionNoActions() throws Exception {
180         final String codebase = "http://example.com";
181         final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader");
182         controller.addCustomPermission(codebase, customPermission);
183         assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission));
184     }
185 
186     @Test
testAddCustomPermissionEmptyActions()187     public void testAddCustomPermissionEmptyActions() throws Exception {
188         final String codebase = "http://example.com";
189         final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", "");
190         controller.addCustomPermission(codebase, customPermission);
191         assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission));
192     }
193 
194     @Test
testClearCustomPermissionsNoActions()195     public void testClearCustomPermissionsNoActions() throws Exception {
196         final String codebase = "http://example.com";
197         final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader");
198         controller.addCustomPermission(codebase, customPermission);
199         assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission));
200         controller.clearCustomCodebase(codebase);
201         assertEquals(0, controller.getCustomPermissions(codebase).size());
202     }
203 
204     @Test
testClearCustomPermissionsEmptyActions()205     public void testClearCustomPermissionsEmptyActions() throws Exception {
206         final String codebase = "http://example.com";
207         final CustomPermission customPermission = new CustomPermission("java.lang.RuntimePermission", "createClassLoader", "");
208         controller.addCustomPermission(codebase, customPermission);
209         assertTrue("Controller custom permissions should include " + customPermission + " but did not", controller.getCustomPermissions(codebase).contains(customPermission));
210         controller.clearCustomCodebase(codebase);
211         assertEquals(0, controller.getCustomPermissions(codebase).size());
212     }
213 
214     @Test
testReturnedCodebasesIsCopy()215     public void testReturnedCodebasesIsCopy() throws Exception {
216         final Collection<String> original = controller.getCodebases();
217         original.add("some invalid value");
218         original.remove("");
219         final Collection<String> second = controller.getCodebases();
220         assertEquals("Controller should have no codebases", 0, second.size());
221     }
222 
223     @Test
testReturnedPermissionsMapIsCopy()224     public void testReturnedPermissionsMapIsCopy() throws Exception {
225         final Map<PolicyEditorPermissions, Boolean> original = controller.getPermissions("");
226         for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) {
227             original.put(perm, true);
228         }
229         final Map<PolicyEditorPermissions, Boolean> second = controller.getPermissions("");
230         for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : second.entrySet()) {
231             assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue());
232         }
233     }
234 
235     @Test
testReturnedCustomPermissionsSetIsCopy()236     public void testReturnedCustomPermissionsSetIsCopy() throws Exception {
237         final Collection<CustomPermission> original = controller.getCustomPermissions("");
238         assertTrue("There should not be any custom permissions to start", original.isEmpty());
239         original.add(new CustomPermission("java.io.FilePermission", "*", "write"));
240         final Collection<CustomPermission> second = controller.getCustomPermissions("");
241         assertTrue("The custom permission should not have been present", second.isEmpty());
242     }
243 
244     @Test
testDefaultPermissionsAllFalse()245     public void testDefaultPermissionsAllFalse() throws Exception {
246         final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions("");
247         controller.addCodebase("http://example.com");
248         final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions("http://example.com");
249         for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : defaultMap.entrySet()) {
250             assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue());
251         }
252         for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : addedMap.entrySet()) {
253             assertFalse("Permission " + entry.getKey() + " should be false", entry.getValue());
254         }
255     }
256 
257     @Test
testAllPermissionsRepresented()258     public void testAllPermissionsRepresented() throws Exception {
259         final Map<PolicyEditorPermissions, Boolean> defaultMap = controller.getPermissions("");
260         controller.addCodebase("http://example.com");
261         final Map<PolicyEditorPermissions, Boolean> addedMap = controller.getPermissions("http://example.com");
262         assertTrue("Default codebase permissions keyset should be the same size as enum values set",
263                 defaultMap.keySet().size() == PolicyEditorPermissions.values().length);
264         assertTrue("Added codebase permissions keyset should be the same size as enum values set",
265                 addedMap.keySet().size() == PolicyEditorPermissions.values().length);
266         for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) {
267             assertTrue("Permission " + perm + " should be in the editor's codebase keyset", defaultMap.keySet().contains(perm));
268         }
269         for (final PolicyEditorPermissions perm : PolicyEditorPermissions.values()) {
270             assertTrue("Permission " + perm + " should be in the editor's codebase keyset", addedMap.keySet().contains(perm));
271         }
272     }
273 
274     @Test
testSetGetPermission()275     public void testSetGetPermission() throws Exception {
276         final String codebase = "http://example.com";
277         controller.addCodebase(codebase);
278         final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD;
279         assertFalse("Clipboard permission should not be initially granted", controller.getPermission(codebase, permission));
280         controller.setPermission(codebase, permission, true);
281         assertTrue("Clipboard permission should be granted after being set", controller.getPermission(codebase, permission));
282     }
283 
284     @Test
testClearPermission()285     public void testClearPermission() throws Exception {
286         final String codebase = "http://example.com";
287         controller.addCodebase(codebase);
288         final PolicyEditorPermissions permission = PolicyEditorPermissions.CLIPBOARD;
289         assertFalse("Clipboard permission should not be initially granted", controller.getPermission(codebase, permission));
290         controller.setPermission(codebase, permission, true);
291         assertTrue("Clipboard permission should be granted after being set", controller.getPermission(codebase, permission));
292         controller.clearPermissions();
293         for (final String cb : controller.getCodebases()) {
294             for (final Map.Entry<PolicyEditorPermissions, Boolean> entry : controller.getPermissions(cb).entrySet()) {
295                 assertFalse("Permission " + entry.getKey() + " should be false for codebase " + cb, entry.getValue());
296             }
297         }
298         assertEquals(0, controller.getCodebases().size());
299     }
300 
301     @Test
testCodebaseTrailingSlashesDoNotMatch()302     public void testCodebaseTrailingSlashesDoNotMatch() throws Exception {
303         final Collection<String> toAdd = Arrays.asList("http://redhat.com", "http://redhat.com/");
304         for (final String cb : toAdd) {
305             controller.addCodebase(cb);
306         }
307         final Collection<String> codebases = controller.getCodebases();
308         for (final String codebase : toAdd) {
309             assertTrue("Controller should have " + codebase, codebases.contains(codebase));
310         }
311     }
312 
313     @Test
testOpenAndParsePolicyFile()314     public void testOpenAndParsePolicyFile() throws Exception {
315         final String codebase = "http://example.com";
316         final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD;
317         final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions);
318         final CustomPermission customPermission = new CustomPermission("com.example.CustomPermission", PermissionTarget.USER_HOME.target, PermissionActions.FILE_ALL.rawString());
319         final Collection<CustomPermission> customPermissions = new HashSet<>(Collections.singleton(customPermission));
320         final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions);
321         FileUtils.saveFile(policyEntry.toString(), new File(tempFilePath));
322         controller.openAndParsePolicyFile();
323         assertEquals("Controller should have one codebase", 1, controller.getCodebases().size());
324         assertTrue("Controller should have codebase " + codebase, controller.getCodebases().contains(codebase));
325         assertTrue("Controller should grant " + editorPermissions, controller.getPermission(codebase, editorPermissions));
326         assertEquals("Custom permission sets were not equal", customPermissions, controller.getCustomPermissions(codebase));
327     }
328 
329     @Test
testSavePolicyFile()330     public void testSavePolicyFile() throws Exception {
331         final String codebase = "http://example.com";
332         final PolicyEditorPermissions editorPermissions = PolicyEditorPermissions.CLIPBOARD;
333         final Collection<PolicyEditorPermissions> permissions = Collections.singleton(editorPermissions);
334         final CustomPermission customPermission = new CustomPermission(PermissionType.FILE_PERMISSION, PermissionTarget.USER_HOME, PermissionActions.FILE_ALL);
335         final Collection<CustomPermission> customPermissions = Collections.singleton(customPermission);
336         final PolicyEntry policyEntry = new PolicyEntry(codebase, permissions, customPermissions);
337         controller.addPolicyEntry(policyEntry);
338         controller.savePolicyFile();
339         final String fileContent = FileUtils.loadFileAsString(new File(tempFilePath));
340         assertTrue("Saved file should contain policy entry as string", fileContent.contains(policyEntry.toString()));
341     }
342 }
343