Home | History | Annotate | Download | only in security
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 /**
     19  * @author Boris V. Kuznetsov
     20  * @version $Revision$
     21  */
     22 
     23 package org.apache.harmony.security.tests.java.security;
     24 
     25 import java.io.ByteArrayInputStream;
     26 import java.io.ByteArrayOutputStream;
     27 import java.io.IOException;
     28 import java.io.InputStream;
     29 import java.io.PrintStream;
     30 import java.security.NoSuchAlgorithmException;
     31 import java.security.Permission;
     32 import java.security.Provider;
     33 import java.security.Security;
     34 import java.security.SecurityPermission;
     35 import java.security.Provider.Service;
     36 import java.util.Collection;
     37 import java.util.ConcurrentModificationException;
     38 import java.util.HashMap;
     39 import java.util.Iterator;
     40 import java.util.Locale;
     41 import java.util.Set;
     42 import java.util.Map.Entry;
     43 
     44 import junit.framework.TestCase;
     45 
     46 /**
     47  * Tests for <code>Provider</code> constructor and methods
     48  *
     49  */
     50 public class ProviderTest extends TestCase {
     51     /*
     52      * Implementation note: The algorithm name ASH-1 might seem a bit strange,
     53      * but since the algorithms cannot be uninstalled anymore we need to make
     54      * sure there are not side-effects on other tests. Simply inserting SHA-1
     55      * destroys the existing provider infrastructure.
     56      */
     57 
     58     Provider[] storedProviders;
     59 
     60     Provider p;
     61 
     62     /*
     63      * @see TestCase#setUp()
     64      */
     65     protected void setUp() throws Exception {
     66         super.setUp();
     67 
     68         storedProviders = Security.getProviders();
     69 
     70         p = new MyProvider();
     71     }
     72 
     73     @Override
     74     protected void tearDown() throws Exception {
     75         p.remove("MessageDigest.ASH-1");
     76         p.remove("MessageDigest.abc");
     77         p.remove("Alg.Alias.MessageDigest.ASH1");
     78 
     79         for (Provider p: Security.getProviders()) {
     80             Security.removeProvider(p.getName());
     81         }
     82 
     83         for (Provider p: storedProviders) {
     84             Security.addProvider(p);
     85         }
     86 
     87         super.tearDown();
     88     }
     89 
     90     /*
     91      * Class under test for void Provider()
     92      */
     93     public final void testProvider() {
     94         if (!p.getProperty("Provider.id name").equals(
     95                 String.valueOf(p.getName()))) {
     96             fail("Incorrect \"Provider.id name\" value");
     97         }
     98         if (!p.getProperty("Provider.id version").equals(
     99                 String.valueOf(p.getVersion()))) {
    100             fail("Incorrect \"Provider.id version\" value");
    101         }
    102         if (!p.getProperty("Provider.id info").equals(
    103                 String.valueOf(p.getInfo()))) {
    104             fail("Incorrect \"Provider.id info\" value");
    105         }
    106         if (!p.getProperty("Provider.id className").equals(
    107                 p.getClass().getName())) {
    108             fail("Incorrect \"Provider.id className\" value");
    109         }
    110     }
    111 
    112     public final void testClear() {
    113         p.clear();
    114         assertNull(p.getProperty("MessageDigest.SHA-1"));
    115     }
    116 
    117     /*
    118      * Class under test for void Provider(String, double, String)
    119      */
    120     public final void testProviderStringdoubleString() {
    121         Provider p = new MyProvider("Provider name", 123.456, "Provider info");
    122         assertEquals("Provider name", p.getName());
    123         assertEquals(123.456, p.getVersion(), 0L);
    124         assertEquals("Provider info", p.getInfo());
    125     }
    126 
    127     public final void testGetName() {
    128         assertEquals("MyProvider", p.getName());
    129     }
    130 
    131     public final void testGetVersion() {
    132         assertEquals(1.0, p.getVersion(), 0L);
    133     }
    134 
    135     public final void testGetInfo() {
    136         assertEquals("Provider for testing", p.getInfo());
    137     }
    138 
    139     /*
    140      * Class under test for void putAll(Map)
    141      */
    142     public final void testPutAllMap() {
    143         HashMap hm = new HashMap();
    144         hm.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
    145         hm.put("Property 1", "value 1");
    146         hm.put("serviceName.algName attrName", "attrValue");
    147         hm.put("Alg.Alias.engineClassName.aliasName", "standardName");
    148         p.putAll(hm);
    149         if (!"value 1".equals(p.getProperty("Property 1").trim()) ||
    150                 !"attrValue".equals(p.getProperty("serviceName.algName attrName").trim()) ||
    151                 !"standardName".equals(p.getProperty("Alg.Alias.engineClassName.aliasName").trim()) ||
    152                 !"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.SHA-1").trim()) ) {
    153             fail("Incorrect property value");
    154         }
    155     }
    156 
    157     /*
    158      * Class under test for Set entrySet()
    159      */
    160     public final void testEntrySet() {
    161         p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
    162 
    163         Set s = p.entrySet();
    164         try {
    165             s.clear();
    166             fail("Must return unmodifiable set");
    167         } catch (UnsupportedOperationException e) {
    168         }
    169 
    170         assertEquals("Incorrect set size", 8, s.size());
    171 
    172         for (Iterator it = s.iterator(); it.hasNext();) {
    173             Entry e = (Entry)it.next();
    174             String key = (String)e.getKey();
    175             String val = (String)e.getValue();
    176             if (key.equals("MessageDigest.SHA-1") && val.equals("SomeClassName")) {
    177                 continue;
    178             }
    179             if (key.equals("Alg.Alias.MessageDigest.SHA1") && val.equals("SHA-1")) {
    180                 continue;
    181             }
    182             if (key.equals("MessageDigest.abc") && val.equals("SomeClassName")) {
    183                 continue;
    184             }
    185             if (key.equals("Provider.id className") && val.equals(p.getClass().getName())) {
    186                 continue;
    187             }
    188             if (key.equals("Provider.id name") && val.equals("MyProvider")) {
    189                 continue;
    190             }
    191             if (key.equals("MessageDigest.SHA-256") && val.equals("aaa.bbb.ccc.ddd")) {
    192                 continue;
    193             }
    194             if (key.equals("Provider.id version") && val.equals("1.0")) {
    195                 continue;
    196             }
    197             if (key.equals("Provider.id info") && val.equals("Provider for testing")) {
    198                 continue;
    199             }
    200             fail("Incorrect set");
    201         }
    202     }
    203 
    204     public final void testForEach() {
    205         p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
    206         p.put("MessageDigest.abc", "value 1");
    207 
    208         HashMap<String, String> hm = new HashMap<>();
    209         p.forEach((k,v)-> hm.put((String)k, (String)v));
    210 
    211         assertEquals(p.size(), hm.size());
    212         for(String key : hm.keySet()) {
    213           assertEquals(p.get(key), hm.get(key));
    214         }
    215     }
    216 
    217     public void testForEachNPE() throws Exception {
    218         try {
    219             p.forEach(null);
    220             fail();
    221         } catch(NullPointerException expected) {}
    222     }
    223 
    224     public void testForEachCME() throws Exception {
    225         p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
    226         p.put("MessageDigest.abc", "value 1");
    227         try {
    228             p.forEach(new java.util.function.BiConsumer<Object, Object>() {
    229                     @Override
    230                     public void accept(Object k, Object v) {p.put("foo", "bar");}
    231                 });
    232             fail();
    233         } catch(ConcurrentModificationException expected) {}
    234     }
    235 
    236     /*
    237      * Class under test for Set keySet()
    238      */
    239     public final void testKeySet() {
    240         p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
    241 
    242         Set<Object> s = p.keySet();
    243         try {
    244             s.clear();
    245         } catch (UnsupportedOperationException e) {
    246         }
    247         Set s1 = p.keySet();
    248 
    249         assertNotSame(s, s1);
    250         assertFalse(s1.isEmpty());
    251         assertEquals(8, s1.size());
    252 
    253         assertTrue(s1.contains("MessageDigest.SHA-256"));
    254         assertTrue(s1.contains("MessageDigest.SHA-1"));
    255         assertTrue(s1.contains("Alg.Alias.MessageDigest.SHA1"));
    256         assertTrue(s1.contains("MessageDigest.abc"));
    257         assertTrue(s1.contains("Provider.id info"));
    258         assertTrue(s1.contains("Provider.id className"));
    259         assertTrue(s1.contains("Provider.id version"));
    260         assertTrue(s1.contains("Provider.id name"));
    261     }
    262 
    263     /*
    264      * Class under test for Collection values()
    265      */
    266     public final void testValues() {
    267         p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
    268 
    269         Collection<Object> c = p.values();
    270         try {
    271             c.clear();
    272         } catch (UnsupportedOperationException e) {
    273         }
    274         Collection c1 = p.values();
    275 
    276         assertNotSame(c, c1);
    277         assertFalse(c1.isEmpty());
    278         assertEquals(8, c1.size());
    279 
    280         assertTrue(c1.contains("MyProvider"));
    281         assertTrue(c1.contains("aaa.bbb.ccc.ddd"));
    282         assertTrue(c1.contains("Provider for testing"));
    283         assertTrue(c1.contains("1.0"));
    284         assertTrue(c1.contains("SomeClassName"));
    285         assertTrue(c1.contains("SHA-1"));
    286         assertTrue(c1.contains(p.getClass().getName()));
    287     }
    288 
    289     /*
    290      * Class under test for Object put(Object, Object)
    291      */
    292     public final void testPutObjectObject() {
    293         p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
    294         p.put("Type.Algorithm", "className");
    295         assertEquals("aaa.bbb.ccc.ddd", p.getProperty("MessageDigest.SHA-1")
    296                 .trim());
    297 
    298         Set services = p.getServices();
    299         assertEquals(3, services.size());
    300 
    301         for (Iterator it = services.iterator(); it.hasNext();) {
    302             Provider.Service s = (Provider.Service)it.next();
    303             if ("Type".equals(s.getType()) &&
    304                     "Algorithm".equals(s.getAlgorithm()) &&
    305                     "className".equals(s.getClassName())) {
    306                 continue;
    307             }
    308             if ("MessageDigest".equals(s.getType()) &&
    309                     "SHA-1".equals(s.getAlgorithm()) &&
    310                     "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
    311                 continue;
    312             }
    313             if ("MessageDigest".equals(s.getType()) &&
    314                     "abc".equals(s.getAlgorithm()) &&
    315                     "SomeClassName".equals(s.getClassName())) {
    316                 continue;
    317             }
    318             fail("Incorrect service");
    319         }
    320     }
    321 
    322     /*
    323      * Class under test for Object remove(Object)
    324      */
    325     public final void testRemoveObject() {
    326         Object o = p.remove("MessageDigest.SHA-1");
    327 
    328         assertEquals("SomeClassName", o);
    329         assertNull(p.getProperty("MessageDigest.SHA-1"));
    330         assertEquals(1, p.getServices().size());
    331     }
    332 
    333     public final void testService1() {
    334         p.put("MessageDigest.SHA-1", "AnotherClassName");
    335         Provider.Service s = p.getService("MessageDigest", "SHA-1");
    336         assertEquals("AnotherClassName", s.getClassName());
    337     }
    338 
    339     public final void testGetServiceCaseSensitivity() {
    340         p.put("i.I", "foo");
    341 
    342         Locale defaultLocale = Locale.getDefault();
    343         Locale.setDefault(new Locale("tr", "TR"));
    344         try {
    345             assertEquals("foo", p.getService("i", "i").getClassName());
    346             assertEquals("foo", p.getService("i", "I").getClassName());
    347             assertNull(p.getService("\u0130", "\u0130")); // Turkish dotless i and dotted I
    348             assertNull(p.getService("\u0131", "\u0131"));
    349         } finally {
    350             Locale.setDefault(defaultLocale);
    351         }
    352     }
    353 
    354     // Regression for HARMONY-2760.
    355     public void testConstructor() {
    356         MyProvider myProvider = new MyProvider(null, 1, null);
    357         assertNull(myProvider.getName());
    358         assertNull(myProvider.getInfo());
    359         assertEquals("null", myProvider.getProperty("Provider.id name"));
    360         assertEquals("null", myProvider.getProperty("Provider.id info"));
    361     }
    362 
    363     class MyProvider extends Provider {
    364         MyProvider() {
    365             super("MyProvider", 1.0, "Provider for testing");
    366             put("MessageDigest.SHA-1", "SomeClassName");
    367             put("MessageDigest.abc", "SomeClassName");
    368             put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
    369         }
    370 
    371         MyProvider(String name, double version, String info) {
    372             super(name, version, info);
    373         }
    374 
    375         // BEGIN Android-added
    376         public void putService(Provider.Service s) {
    377             super.putService(s);
    378         }
    379         // END Android-added
    380 
    381         // BEGIN Android-added
    382         public void removeService(Provider.Service s) {
    383             super.removeService(s);
    384         }
    385         // END Android-added
    386 
    387         // BEGIN Android-added
    388         public int getNumServices() {
    389             return getServices().size();
    390         }
    391         // END Android-added
    392     }
    393 
    394     // BEGIN Android-added
    395     public final void testService2() {
    396         Provider[] pp = Security.getProviders("MessageDigest.ASH-1");
    397         if (pp == null) {
    398             return;
    399         }
    400         Provider p2 = pp[0];
    401         String old = p2.getProperty("MessageDigest.ASH-1");
    402         p2.put("MessageDigest.ASH-1", "AnotherClassName");
    403         Provider.Service s = p2.getService("MessageDigest", "ASH-1");
    404         if (!"AnotherClassName".equals(s.getClassName())) {
    405             fail("Incorrect class name " + s.getClassName());
    406         }
    407         try {
    408             s.newInstance(null);
    409             fail("No expected NoSuchAlgorithmException");
    410         } catch (NoSuchAlgorithmException e) {
    411         }
    412     }
    413     // END Android-added
    414 
    415     // BEGIN Android-added
    416     public final void testGetServices() {
    417         MyProvider myProvider = new MyProvider(null, 1, null);
    418         Set<Provider.Service> services = myProvider.getServices();
    419         assertEquals(0, services.size());
    420 
    421         Provider.Service s[] = new Provider.Service[3];
    422 
    423         s[0] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
    424                 null, null);
    425         s[1] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
    426                 null, null);
    427         s[2] = new Provider.Service(myProvider, "type3", "algorithm3", "className3",
    428                 null, null);
    429         myProvider.putService(s[0]);
    430         myProvider.putService(s[1]);
    431         assertEquals(2, myProvider.getNumServices());
    432         Set<Service> actual = myProvider.getServices();
    433 
    434         assertTrue(actual.contains(s[0]));
    435         assertTrue(actual.contains(s[1]));
    436         assertTrue(!actual.contains(s[2]));
    437 
    438         myProvider.removeService(s[1]);
    439         actual = myProvider.getServices();
    440         assertEquals(1, myProvider.getNumServices());
    441 
    442         assertTrue(actual.contains(s[0]));
    443         assertTrue(!actual.contains(s[1]));
    444         assertTrue(!actual.contains(s[2]));
    445 
    446         myProvider.putService(s[2]);
    447         actual = myProvider.getServices();
    448         assertEquals(2, myProvider.getNumServices());
    449         assertTrue(actual.contains(s[0]));
    450         assertTrue(!actual.contains(s[1]));
    451         assertTrue(actual.contains(s[2]));
    452     }
    453     // END Android-added
    454 
    455     // BEGIN Android-added
    456     public final void testPutService() {
    457         MyProvider myProvider = new MyProvider(null, 1, null);
    458         Provider.Service s[] = new Provider.Service[3];
    459 
    460         s[0] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
    461                 null, null);
    462         s[1] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
    463                 null, null);
    464         s[2] = new Provider.Service(myProvider, "type3", "algorithm3", "className3",
    465                 null, null);
    466         myProvider.putService(s[0]);
    467         myProvider.putService(s[1]);
    468         assertEquals(2, myProvider.getNumServices());
    469         Set<Service> actual = myProvider.getServices();
    470 
    471         assertTrue(actual.contains(s[0]));
    472         assertTrue(actual.contains(s[1]));
    473         assertTrue(!actual.contains(s[2]));
    474 
    475         myProvider.removeService(s[1]);
    476         assertEquals(1, myProvider.getNumServices());
    477         actual = myProvider.getServices();
    478 
    479         assertTrue(actual.contains(s[0]));
    480         assertTrue(!actual.contains(s[1]));
    481         assertTrue(!actual.contains(s[2]));
    482 
    483         myProvider.putService(s[2]);
    484         actual = myProvider.getServices();
    485         assertEquals(2, myProvider.getNumServices());
    486         assertTrue(actual.contains(s[0]));
    487         assertTrue(!actual.contains(s[1]));
    488         assertTrue(actual.contains(s[2]));
    489 
    490         myProvider.putService(s[2]);
    491         actual = myProvider.getServices();
    492         assertEquals(2, myProvider.getNumServices());
    493         assertTrue(actual.contains(s[0]));
    494         assertTrue(!actual.contains(s[1]));
    495         assertTrue(actual.contains(s[2]));
    496 
    497         try {
    498             myProvider.putService(null);
    499             fail("NullPointerException expected");
    500         } catch (NullPointerException e) {
    501             // expected
    502         }
    503     }
    504     // END Android-added
    505 
    506     // BEGIN Android-added
    507     public final void testRemoveService() {
    508         MyProvider myProvider = new MyProvider(null, 1, null);
    509         try {
    510             myProvider.removeService(null);
    511             fail("NullPoiterException expected");
    512         } catch (NullPointerException e) {
    513             // expected
    514         }
    515 
    516         Provider.Service s[] = new Provider.Service[3];
    517 
    518         s[0] = new Provider.Service(myProvider, "type0", "algorithm0", "className0",
    519                 null, null);
    520         s[1] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
    521                 null, null);
    522         s[2] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
    523                 null, null);
    524 
    525         try {
    526             myProvider.removeService(s[0]);
    527         } catch (NullPointerException e) {
    528             fail("Unexpected exception");
    529         }
    530 
    531         myProvider.putService(s[0]);
    532         myProvider.putService(s[1]);
    533         myProvider.putService(s[2]);
    534         assertEquals(3, myProvider.getNumServices());
    535         Set<Service> actual = myProvider.getServices();
    536 
    537         assertTrue(actual.contains(s[0]));
    538         assertTrue(actual.contains(s[1]));
    539         assertTrue(actual.contains(s[2]));
    540 
    541         myProvider.removeService(s[1]);
    542         assertEquals(2, myProvider.getNumServices());
    543         actual = myProvider.getServices();
    544 
    545         assertTrue(actual.contains(s[0]));
    546         assertTrue(!actual.contains(s[1]));
    547         assertTrue(actual.contains(s[2]));
    548 
    549         myProvider.removeService(s[0]);
    550         assertEquals(1, myProvider.getNumServices());
    551         actual = myProvider.getServices();
    552 
    553         assertTrue(!actual.contains(s[0]));
    554         assertTrue(!actual.contains(s[1]));
    555         assertTrue(actual.contains(s[2]));
    556 
    557         myProvider.removeService(s[2]);
    558         assertEquals(0, myProvider.getNumServices());
    559         actual = myProvider.getServices();
    560 
    561         assertTrue(!actual.contains(s[0]));
    562         assertTrue(!actual.contains(s[1]));
    563         assertTrue(!actual.contains(s[2]));
    564 
    565         try {
    566             myProvider.removeService(null);
    567             fail("NullPoiterException expected");
    568         } catch (NullPointerException e) {
    569             // expected
    570         }
    571     }
    572     // END Android-added
    573 
    574     // BEGIN Android-added
    575     public final void testLoad() throws IOException {
    576         InputStream is = new ByteArrayInputStream(writeProperties());
    577         MyProvider myProvider = new MyProvider("name", 1, "info");
    578         myProvider.load(is);
    579         assertEquals("tests.security", myProvider.get("test.pkg"));
    580         assertEquals("Unit Tests", myProvider.get("test.proj"));
    581         assertNull(myProvider.get("#commented.entry"));
    582 
    583         assertEquals("info", myProvider.get("Provider.id info"));
    584         String className = myProvider.getClass().toString();
    585         assertEquals(
    586                 className.substring("class ".length(), className.length()),
    587                 myProvider.get("Provider.id className"));
    588         assertEquals("1.0", myProvider.get("Provider.id version"));
    589 
    590         try {
    591             myProvider.load((InputStream) null);
    592             fail("NullPointerException expected");
    593         } catch (NullPointerException e) {
    594             // expected
    595         }
    596     }
    597     // END Android-added
    598 
    599     // BEGIN Android-added
    600     public final void testLoad2() {
    601         class TestInputStream extends InputStream {
    602             @Override
    603             public int read() throws IOException {
    604                 throw new IOException();
    605             }
    606         }
    607 
    608         MyProvider p = new MyProvider();
    609         try {
    610             p.load(new TestInputStream());
    611             fail("expected IOException");
    612         } catch (IOException e) {
    613             // expected
    614         }
    615     }
    616     // END Android-added
    617 
    618     // BEGIN Android-added
    619     protected byte[] writeProperties() {
    620         ByteArrayOutputStream bout = new ByteArrayOutputStream();
    621         PrintStream ps = new PrintStream(bout);
    622         ps.println("#commented.entry=Bogus");
    623         ps.println("test.pkg=tests.security");
    624         ps.println("test.proj=Unit Tests");
    625         ps.close();
    626         return bout.toByteArray();
    627     }
    628     // END Android-added
    629 
    630     // BEGIN Android-added
    631     static class TestSecurityManager extends SecurityManager {
    632         boolean called = false;
    633         private final String permissionName;
    634 
    635         public TestSecurityManager(String permissionName) {
    636             this.permissionName = permissionName;
    637         }
    638 
    639         @Override
    640         public void checkPermission(Permission permission) {
    641             if (permission instanceof SecurityPermission) {
    642                 if (permissionName.equals(permission.getName())) {
    643                     called = true;
    644                 }
    645             }
    646         }
    647     }
    648     // END Android-added
    649 }
    650