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