1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * 
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * The contents of this file are subject to the terms of either the Universal Permissive License
   7  * v 1.0 as shown at http://oss.oracle.com/licenses/upl
   8  *
   9  * or the following license:
  10  *
  11  * Redistribution and use in source and binary forms, with or without modification, are permitted
  12  * provided that the following conditions are met:
  13  * 
  14  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
  15  * and the following disclaimer.
  16  * 
  17  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
  18  * conditions and the following disclaimer in the documentation and/or other materials provided with
  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.ui.common.security;
  34 
  35 import static org.junit.Assert.assertEquals;
  36 import static org.junit.Assert.assertFalse;
  37 import static org.junit.Assert.assertNull;
  38 import static org.junit.Assert.assertTrue;
  39 import static org.junit.Assert.fail;
  40 
  41 import java.util.Arrays;
  42 import java.util.Collections;
  43 import java.util.HashSet;
  44 
  45 import org.junit.Assume;
  46 import org.junit.BeforeClass;
  47 import org.junit.Test;
  48 import org.osgi.service.prefs.Preferences;
  49 
  50 import org.openjdk.jmc.ui.common.security.SecureStore;
  51 import org.openjdk.jmc.ui.common.security.SecurityException;
  52 import org.openjdk.jmc.ui.common.util.Environment;
  53 
  54 @SuppressWarnings("nls")
  55 public class SecureStoreTest {
  56 
  57         private final String pwd = "test";
  58         private final String family = "family";
  59         private final String family2 = "family2";
  60         private final String value1 = "1";
  61         private final String value2 = "2";
  62 
  63         @BeforeClass
  64         public static void beforeClass() {
  65                 Assume.assumeFalse("Skipping testing on Linux due to possible lack of entropy",
  66                                 Environment.getOSType() == Environment.OSType.LINUX);
  67         }
  68 
  69         @Test
  70         public void testEncryptDecrypt() throws Exception {
  71                 Preferences prefs = new DummyPreferences();
  72                 SecureStore store = new SecureStore(prefs);
  73                 store.initialize();
  74                 store.setPassword(pwd);
  75                 SecureStore decryptedStore = new SecureStore(prefs);
  76                 assertTrue(!decryptedStore.isInitialized());
  77                 decryptedStore.initialize(pwd);
  78                 assertTrue(decryptedStore.isInitialized());
  79                 assertEquals(store.insert(null, true, value2), decryptedStore.insert(null, true, value2));
  80                 assertEquals(store.insert(family, true, value1), decryptedStore.insert(family, true, value1));
  81                 assertEquals(store.insert(family, false, value1), family);
  82                 assertFalse(store.insert(family, true, value1).equals(decryptedStore.insert(null, true, value1)));
  83 
  84         }
  85 
  86         @Test(expected = SecurityException.class)
  87         public void testInvalidCipher() throws Exception {
  88                 Preferences prefs = new DummyPreferences();
  89                 SecureStore store = new SecureStore(prefs);
  90                 store.initialize();
  91                 store.setPassword(pwd);
  92                 store.setEncryptionCipher("UnknownCipher");
  93         }
  94 
  95         @Test
  96         public void testInsert() throws Exception {
  97                 Preferences prefs = new DummyPreferences();
  98                 SecureStore store = new SecureStore(prefs);
  99                 store.initialize();
 100                 store.setPassword(pwd);
 101                 String key = store.insert(family, true, value1);
 102                 String key2 = store.insert(family, true, value1);
 103                 String key3 = store.insert(family, true, new String[] {value1, value2});
 104                 assertFalse(key.equals(key2));
 105                 SecureStore decryptedStore = new SecureStore(prefs);
 106                 decryptedStore.initialize(pwd);
 107                 assertEquals(value1, decryptedStore.get(key));
 108                 assertEquals(2, ((String[]) decryptedStore.get(key3)).length);
 109         }
 110 
 111         @Test
 112         public void testRemove() throws Exception {
 113                 Preferences prefs = new DummyPreferences();
 114                 SecureStore store = new SecureStore(prefs);
 115                 store.initialize();
 116                 store.setPassword(pwd);
 117                 String key = store.insert(family, true, value1);
 118                 String key2 = store.insert(family, true, value1);
 119                 SecureStore decryptedStore = new SecureStore(prefs);
 120                 assertTrue(decryptedStore.hasKey(key2));
 121                 assertNull(value1, decryptedStore.remove(key2));
 122                 assertFalse(decryptedStore.hasKey(key2));
 123                 decryptedStore.initialize(pwd);
 124                 assertEquals(value1, decryptedStore.get(key));
 125                 assertEquals(value1, decryptedStore.remove(key));
 126                 assertNull(decryptedStore.get(key));
 127                 assertNull(decryptedStore.get(key2));
 128         }
 129 
 130         @Test
 131         public void testInvalidPassword() throws Exception {
 132                 Preferences prefs = new DummyPreferences();
 133                 SecureStore store = new SecureStore(prefs);
 134                 store.initialize();
 135                 store.setPassword(pwd);
 136                 store.insert(null, true, value1);
 137                 store = new SecureStore(prefs);
 138                 try {
 139                         store.initialize("other");
 140                         fail();
 141                 } catch (Exception e) {
 142                 }
 143         }
 144 
 145         @Test
 146         public void testAllCiphers() throws Exception {
 147                 Preferences prefs = new DummyPreferences();
 148                 SecureStore store = new SecureStore(prefs);
 149                 store.initialize();
 150                 store.setPassword(pwd);
 151                 String key = store.insert(null, true, value1);
 152                 for (String cipher : SecureStore.ENCRYPTION_CIPHERS) {
 153                         store.setEncryptionCipher(cipher);
 154                         store = new SecureStore(prefs);
 155                         store.initialize(pwd);
 156                         assertEquals(cipher, store.getEncryptionCipher());
 157                         assertEquals(value1, store.get(key));
 158                         System.out.println(cipher + " tested ok");
 159                 }
 160         }
 161 
 162         @Test
 163         public void testChangePassword() throws Exception {
 164                 Preferences prefs = new DummyPreferences();
 165                 SecureStore store = new SecureStore(prefs);
 166                 store.initialize();
 167                 store.setPassword(pwd);
 168                 String key = store.insert(null, true, value1);
 169                 store = new SecureStore(prefs);
 170                 store.initialize(pwd);
 171                 store.setPassword("newPwd");
 172                 store = new SecureStore(prefs);
 173                 store.initialize("newPwd");
 174                 assertEquals(value1, store.get(key));
 175         }
 176 
 177         @Test
 178         public void testClearFamily() throws Exception {
 179                 Preferences prefs = new DummyPreferences();
 180                 SecureStore store = new SecureStore(prefs);
 181                 store.initialize();
 182                 store.setPassword(pwd);
 183                 String key = store.insert(family, true, value1);
 184                 String key2 = store.insert(family2, true, value1);
 185                 store = new SecureStore(prefs);
 186                 assertTrue(store.hasKey(key));
 187                 assertTrue(store.hasKey(key2));
 188                 store.clearFamily(family, new HashSet<>(Arrays.asList(key)));
 189                 assertTrue(store.hasKey(key));
 190                 store.clearFamily(family, Collections.<String> emptySet());
 191                 assertFalse(store.hasKey(key));
 192                 store.initialize(pwd);
 193                 assertTrue(store.hasKey(key2));
 194                 assertNull(store.get(key));
 195                 assertEquals(value1, store.get(key2));
 196                 store.clearFamily(family2, Collections.<String> emptySet());
 197                 assertNull(value1, store.get(key2));
 198         }
 199 }