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
18package org.apache.harmony.security.tests.java.security;
19
20import java.security.InvalidParameterException;
21import java.security.Provider;
22import java.security.Security;
23import java.util.Hashtable;
24import java.util.Iterator;
25import java.util.Map;
26import java.util.Set;
27
28import tests.support.Support_ProviderTrust;
29import tests.support.Support_TestProvider;
30
31public class Security2Test extends junit.framework.TestCase {
32
33	/**
34	 * @tests java.security.Security#getProviders(java.lang.String)
35	 */
36	public void test_getProvidersLjava_lang_String() {
37		// Test for method void
38		// java.security.Security.getProviders(java.lang.String)
39
40		Hashtable allSupported = new Hashtable();
41		Provider[] allProviders = Security.getProviders();
42
43		// Add all non-alias entries to allSupported
44		for (int i = 0; i < allProviders.length; i++) {
45			Provider provider = allProviders[i];
46			Iterator it = provider.entrySet().iterator();
47			while (it.hasNext()) {
48				Map.Entry entry = (Map.Entry) it.next();
49				String key = (String) entry.getKey();
50				// No aliases and no provider data
51				if (!isAlias(key) && !isProviderData(key)) {
52					addOrIncrementTable(allSupported, key);
53				}
54			}// end while more entries
55		}// end for all providers
56
57		// Now walk through aliases. If an alias has actually been added
58		// to the allSupported table then increment the count of the
59		// entry that is being aliased.
60		for (int i = 0; i < allProviders.length; i++) {
61			Provider provider = allProviders[i];
62			Iterator it = provider.entrySet().iterator();
63			while (it.hasNext()) {
64				Map.Entry entry = (Map.Entry) it.next();
65				String key = (String) entry.getKey();
66				if (isAlias(key)) {
67					String aliasVal = key.substring("ALG.ALIAS.".length());
68					String aliasKey = aliasVal.substring(0, aliasVal
69							.indexOf('.') + 1)
70							+ entry.getValue();
71					// Skip over nonsense alias declarations where alias and
72					// aliased are identical. Such entries can occur.
73					if (!aliasVal.equals(aliasKey)) {
74						// Has a real entry been added for aliasValue ?
75						if (allSupported.containsKey(aliasVal)) {
76							// Add 1 to the provider count of the thing being
77							// aliased
78							addOrIncrementTable(allSupported, aliasKey);
79						}
80					}
81				}
82			}// end while more entries
83		}// end for all providers
84
85		Provider provTest[] = null;
86		Iterator it = allSupported.keySet().iterator();
87		while (it.hasNext()) {
88			String filterString = (String) it.next();
89			try {
90				provTest = Security.getProviders(filterString);
91				int expected = ((Integer) allSupported.get(filterString))
92						.intValue();
93				assertEquals(
94						"Unexpected number of providers returned for filter "
95								+ filterString, expected, provTest.length);
96			} catch (InvalidParameterException e) {
97				// NO OP
98			}
99		}// end while
100
101		// exception
102		try {
103			provTest = Security.getProviders("Signature.SHA1withDSA :512");
104			fail("InvalidParameterException should be thrown <Signature.SHA1withDSA :512>");
105		} catch (InvalidParameterException e) {
106			// Expected
107		}
108	}
109
110	/**
111	 * @param key
112	 * @return
113	 */
114	private boolean isProviderData(String key) {
115		return key.toUpperCase().startsWith("PROVIDER.");
116	}
117
118	/**
119	 * @param key
120	 * @return
121	 */
122	private boolean isAlias(String key) {
123		return key.toUpperCase().startsWith("ALG.ALIAS.");
124	}
125
126	/**
127	 * @param table
128	 * @param key
129	 */
130	private void addOrIncrementTable(Hashtable table, String key) {
131		if (table.containsKey(key)) {
132			Integer before = (Integer) table.get(key);
133			table.put(key, new Integer(before.intValue() + 1));
134		} else {
135			table.put(key, new Integer(1));
136		}
137	}
138
139	/**
140	 * @param filterMap
141	 * @return
142	 */
143	private int getProvidersCount(Map filterMap) {
144		int result = 0;
145		Provider[] allProviders = Security.getProviders();
146
147		// for each provider
148		for (int i = 0; i < allProviders.length; i++) {
149			Provider provider = allProviders[i];
150			Set allProviderKeys = provider.keySet();
151			boolean noMatchFoundForFilterEntry = false;
152
153			// for each filter item
154			Set allFilterKeys = filterMap.keySet();
155			Iterator fkIter = allFilterKeys.iterator();
156			while (fkIter.hasNext()) {
157				String filterString = ((String) fkIter.next()).trim();
158
159				// Remove any "=" characters that may be on the end of the
160				// map keys (no, I don't know why they might be there either
161				// but I have seen them)
162				if (filterString.endsWith("=")) {
163					filterString = filterString.substring(0, filterString
164							.length() - 1);
165				}
166
167				if (filterString != null) {
168					if (filterString.indexOf(' ') == -1) {
169						// Is this filter string in the keys of the
170						// current provider ?
171						if (!allProviderKeys.contains(filterString)) {
172							// Check that the key is not contained as an
173							// alias.
174							if (!allProviderKeys.contains("Alg.Alias."
175									+ filterString)) {
176								noMatchFoundForFilterEntry = true;
177								break; // out of while loop
178							}
179						}
180					} else {
181						// handle filter strings with attribute names
182						if (allProviderKeys.contains(filterString)) {
183							// Does the corresponding values match ?
184							String filterVal = (String) filterMap
185									.get(filterString);
186							String providerVal = (String) provider
187									.get(filterString);
188							if (providerVal == null
189									|| !providerVal.equals(filterVal)) {
190								noMatchFoundForFilterEntry = true;
191								break; // out of while loop
192							}
193						}// end if filter string with named attribute is
194						// found
195					}// end else
196				}// end if non-null key
197			}// end while there are more filter strings for current map
198
199			if (!noMatchFoundForFilterEntry) {
200				// Current provider is a match for the filterMap
201				result++;
202			}
203		}// end for each provider
204
205		return result;
206	}
207
208	/**
209	 * @tests java.security.Security#getProviders(java.util.Map)
210	 */
211	public void test_getProvidersLjava_util_Map() {
212		// Test for method void
213		// java.security.Security.getProviders(java.util.Map)
214
215		Map filter = new Hashtable();
216		filter.put("KeyStore.BKS", "");
217		filter.put("Signature.SHA1withDSA", "");
218		Provider provTest[] = Security.getProviders(filter);
219		if (provTest == null) {
220			assertEquals("Filter : <KeyStore.BKS>,<Signature.SHA1withDSA>",
221					0, getProvidersCount(filter));
222		} else {
223			assertEquals("Filter : <KeyStore.BKS>,<Signature.SHA1withDSA>",
224					getProvidersCount(filter), provTest.length);
225		}
226
227		filter = new Hashtable();
228		filter.put("MessageDigest.MD2", "");
229		filter.put("CertificateFactory.X.509", "");
230		filter.put("KeyFactory.RSA", "");
231		provTest = Security.getProviders(filter);
232		if (provTest == null) {
233			assertEquals("Filter : <MessageDigest.MD2>,<CertificateFactory.X.509>,<KeyFactory.RSA>",
234					0, getProvidersCount(filter));
235		} else {
236			assertEquals(
237					"Filter : <MessageDigest.MD2>,<CertificateFactory.X.509>,<KeyFactory.RSA>",
238					getProvidersCount(filter), provTest.length);
239		}
240
241		filter = new Hashtable();
242		filter.put("MessageDigest.SHA", "");
243		filter.put("CertificateFactory.X.509", "");
244		provTest = Security.getProviders(filter);
245		if (provTest == null) {
246			assertEquals("Filter : <MessageDigest.SHA><CertificateFactory.X.509>",
247					0, getProvidersCount(filter));
248		} else {
249			assertEquals(
250					"Filter : <MessageDigest.SHA><CertificateFactory.X.509>",
251					getProvidersCount(filter), provTest.length);
252		}
253
254		filter = new Hashtable();
255		filter.put("CertificateFactory.X509", "");
256		provTest = Security.getProviders(filter);
257		if (provTest == null) {
258			assertEquals("Filter : <CertificateFactory.X509>",
259					0, getProvidersCount(filter));
260		} else {
261			assertEquals("Filter : <CertificateFactory.X509>",
262					getProvidersCount(filter), provTest.length);
263		}
264
265		filter = new Hashtable();
266		filter.put("Provider.id name", "DRLCertFactory");
267		provTest = Security.getProviders(filter);
268        assertNull("Filter : <Provider.id name, DRLCertFactory >",
269                provTest);
270
271		// exception - no attribute name after the service.algorithm yet we
272		// still supply an expected value. This is not valid.
273		try {
274			filter = new Hashtable();
275			filter.put("Signature.SHA1withDSA", "512");
276			provTest = Security.getProviders(filter);
277			fail("InvalidParameterException should be thrown <Signature.SHA1withDSA><512>");
278		} catch (InvalidParameterException e) {
279			// Expected
280		}
281
282		// exception - space character in the service.algorithm pair. Not valid.
283		try {
284			filter = new Hashtable();
285			filter.put("Signature. KeySize", "512");
286			provTest = Security.getProviders(filter);
287			fail("InvalidParameterException should be thrown <Signature. KeySize><512>");
288		} catch (InvalidParameterException e) {
289			// Expected
290		}
291	}
292
293	/**
294	 * @tests java.security.Security#removeProvider(java.lang.String)
295	 */
296	public void test_removeProviderLjava_lang_String() {
297		// Test for method void
298		// java.security.Security.removeProvider(java.lang.String)
299		Provider test = new Support_TestProvider();
300		Provider entrust = new Support_ProviderTrust();
301		try {
302			// Make sure provider not already loaded. Should do nothing
303			// if not already loaded.
304			Security.removeProvider(test.getName());
305
306			// Now add it
307			int addResult = Security.addProvider(test);
308			assertTrue("Failed to add provider", addResult != -1);
309
310			Security.removeProvider(test.getName());
311			assertNull(
312					"the provider TestProvider is found after it was removed",
313					Security.getProvider(test.getName()));
314
315			// Make sure entrust provider not already loaded. Should do nothing
316			// if not already loaded.
317			Security.removeProvider(entrust.getName());
318
319			// Now add entrust
320			addResult = Security.addProvider(entrust);
321			assertTrue("Failed to add provider", addResult != -1);
322
323			Security.removeProvider(entrust.getName());
324			Provider provTest[] = Security.getProviders();
325			for (int i = 0; i < provTest.length; i++) {
326				assertTrue(
327						"the provider entrust is found after it was removed",
328						provTest[i].getName() != entrust.getName());
329			}
330		} finally {
331			// Tidy up - the following calls do nothing if the providers were
332			// already removed above.
333			Security.removeProvider(test.getName());
334			Security.removeProvider(entrust.getName());
335		}
336	}
337}
338