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//package test.java.tests.api.javax.security.auth;
19package tests.api.javax.security.auth;
20
21import java.net.MalformedURLException;
22import java.net.URL;
23import java.security.AllPermission;
24import java.security.CodeSource;
25import java.security.Permission;
26import java.security.PermissionCollection;
27import java.security.Permissions;
28import java.security.Principal;
29import java.security.ProtectionDomain;
30import java.util.EnumSet;
31import java.util.Enumeration;
32import java.util.HashSet;
33import java.util.Set;
34
35import dalvik.annotation.TestLevel;
36import dalvik.annotation.TestTargetClass;
37import dalvik.annotation.TestTargetNew;
38
39import junit.framework.TestCase;
40
41import javax.security.auth.AuthPermission;
42import javax.security.auth.PrivateCredentialPermission;
43import javax.security.auth.Subject;
44import javax.security.auth.SubjectDomainCombiner;
45import javax.security.auth.x500.X500Principal;
46
47
48/**
49 * Tests for <code>SubjectDomainCombiner</code> class constructors and methods.
50 *
51 */
52@TestTargetClass(SubjectDomainCombiner.class)
53public class SubjectDomainCombinerTest extends TestCase {
54    private final static boolean DEBUG = true;
55
56    SecurityManager old;
57
58    @Override
59    protected void setUp() throws Exception {
60        old = System.getSecurityManager();
61        super.setUp();
62    }
63
64    @Override
65    protected void tearDown() throws Exception {
66        System.setSecurityManager(old);
67        super.tearDown();
68    }
69
70
71    /**
72     * @tests javax.security.auth.SubjectDomainCombiner#SubjectDomainCombiner(Subject subject)
73     */
74    @TestTargetNew(
75        level = TestLevel.COMPLETE,
76        notes = "",
77        method = "SubjectDomainCombiner",
78        args = {Subject.class}
79    )
80    public void test_Constructor_01() {
81        Subject s = new Subject();
82        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
83
84        try {
85            assertEquals(s, c.getSubject());
86        } catch(SecurityException se) {
87
88        }
89    }
90
91    /**
92     * @tests javax.security.auth.SubjectDomainCombiner#getSubject()
93     */
94    @TestTargetNew(
95        level = TestLevel.COMPLETE,
96        notes = "Verifies that Subject associated with this SubjectDomainCombiner is returned",
97        method = "getSubject",
98        args = {}
99    )
100    public void test_getSubject_01() {
101        class TestSecurityManager extends SecurityManager {
102            @Override
103            public void checkPermission(Permission permission) {
104                if (permission instanceof AuthPermission
105                        && "getSubjectFromDomainCombiner".equals(permission.getName())) {
106                    return;
107                }
108                super.checkPermission(permission);
109            }
110        }
111
112        TestSecurityManager sm = new TestSecurityManager();
113        System.setSecurityManager(sm);
114
115        Subject s = new Subject();
116        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
117
118        assertEquals(s, c.getSubject());
119    }
120
121
122    /**
123     * @tests javax.security.auth.SubjectDomainCombiner#getSubject()
124     */
125    @TestTargetNew(
126        level = TestLevel.COMPLETE,
127        notes = "SecurityException to be thrown if caller doesn't have permissions to get the Subject",
128        method = "getSubject",
129        args = {}
130    )
131    public void test_getSubject_02() {
132        class TestSecurityManager extends SecurityManager {
133            @Override
134            public void checkPermission(Permission permission) {
135                if (permission instanceof AuthPermission
136                        && "getSubjectFromDomainCombiner".equals(permission.getName())) {
137                    throw new SecurityException();
138                }
139                super.checkPermission(permission);
140            }
141        }
142
143        TestSecurityManager sm = new TestSecurityManager();
144        System.setSecurityManager(sm);
145
146        Subject s = new Subject();
147        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
148
149        try {
150            c.getSubject();
151            fail("SecurityException expected");
152        } catch(SecurityException se) {
153            // expected
154        }
155    }
156
157    protected final static String locationUrl = "http://localhost";
158
159
160    protected final static String[] currentDomainX500names = { "CN=cd_name,OU=abc,O=corp,C=CH" };
161    protected final static String[] currentDomainPerms = { "getStackTrace",
162                                                           "setIO"
163                                                         };
164
165    protected final static String[] assignedDomainX500names = { "CN=ad_name,OU=def,O=corp,C=US" };
166    protected final static String[] assignedDomainPerms = { "accessDeclaredMembers"
167                                                          };
168
169    protected final static String[] SubjectX500names = { "CN=s_user,OU=abc,O=corp,C=US",
170                                                           "CN=s_user,OU=abc,O=corp,C=RU" };
171    protected final static String subjectPubPerm1 = "readFileDescriptor";
172    protected final static String subjectPvtPerm1 = "writeFileDescriptor";
173
174    /**
175     * @tests javax.security.auth.SubjectDomainCombiner#combine()
176     */
177    @TestTargetNew(
178        level = TestLevel.COMPLETE,
179        notes = "both currentDomains and assignedDomains are not null",
180        method = "combine",
181        args = {ProtectionDomain[].class, ProtectionDomain[].class}
182    )
183    public void test_combine_01() {
184
185        URL url;
186        try {
187            url = new URL(locationUrl);
188        } catch (MalformedURLException mue) {
189            throw new Error(mue);
190        }
191        CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null);
192
193        class MyClassLoader extends ClassLoader {
194            public MyClassLoader() {
195                super();
196            }
197        }
198
199        ClassLoader current_pd_cl = new MyClassLoader() ;
200        ClassLoader assigned_pd_cl = new MyClassLoader() ;
201
202        // current domains
203        ProtectionDomain[] current_pd = createProtectionDomains(cs, current_pd_cl, currentDomainX500names, currentDomainPerms);
204
205        // assigned domains
206        ProtectionDomain[] assigned_pd = createProtectionDomains(cs, assigned_pd_cl, assignedDomainX500names, assignedDomainPerms);
207
208        // subject
209        Subject s = createSubject();
210
211        // combine
212        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
213
214        ProtectionDomain[] r_pd = c.combine(current_pd, assigned_pd);
215        if(DEBUG) {
216            System.out.println("=========== c_pd");
217            dumpPD(current_pd);
218            System.out.println("=========== a_pd");
219            dumpPD(assigned_pd);
220            System.out.println("=========== r_pd");
221            dumpPD(r_pd);
222            System.out.println("===========");
223        }
224
225        for(int i = 0; i < r_pd.length; i++) {
226            ProtectionDomain pd = r_pd[i];
227            // check CodeSource
228            assertTrue("code source mismatch", pd.getCodeSource().equals(cs));
229            boolean cpd = false;
230            // check ClassLoader
231            if(pd.getClassLoader().equals(current_pd_cl)) {
232                cpd = true;
233            } else if(pd.getClassLoader().equals(assigned_pd_cl)) {
234                cpd = false;
235            } else {
236                fail("class loader mismatch");
237            }
238
239            // check principals
240            Principal[] principals = pd.getPrincipals();
241            String[] names;
242            if(cpd == true)    names = SubjectX500names;
243            else               names = assignedDomainX500names;
244
245            for(int j = 0; j < principals.length; j++) {
246                if(contains(names, principals[j].getName()) == false)
247                    fail("principal mismatch ("  + j +") " + principals[j].getName());
248            }
249
250            // check permissions
251            PermissionCollection perms = pd.getPermissions();
252
253            Enumeration<Permission> p = perms.elements();
254            while(p.hasMoreElements()) {
255                Permission pp = p.nextElement();
256
257                String pn = pp.getName();
258
259                if(cpd == true) {
260                    if(contains(currentDomainPerms, pn) == false)
261                        fail("current domains permissions mismatch " + pn);
262                } else {
263                    if(contains(assignedDomainPerms, pn) == false)
264                        fail("assigned domains permissions mismatch " + pn);
265                }
266            }
267        }
268    }
269
270    /**
271     * @tests javax.security.auth.SubjectDomainCombiner#combine()
272     */
273    @TestTargetNew(
274        level = TestLevel.COMPLETE,
275        notes = "assignedDomains is null",
276        method = "combine",
277        args = {ProtectionDomain[].class, ProtectionDomain[].class}
278    )
279    public void test_combine_02() {
280
281        URL url;
282        try {
283            url = new URL(locationUrl);
284        } catch (MalformedURLException mue) {
285            throw new Error(mue);
286        }
287        CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null);
288
289        class MyClassLoader extends ClassLoader {
290            public MyClassLoader() {
291                super();
292            }
293        }
294
295        ClassLoader current_pd_cl = new MyClassLoader() ;
296        ClassLoader assigned_pd_cl = new MyClassLoader() ;
297
298        // current domains
299        ProtectionDomain[] current_pd = createProtectionDomains(cs, current_pd_cl, currentDomainX500names, currentDomainPerms);
300
301        // assigned domains
302        ProtectionDomain[] assigned_pd = null;
303
304        // subject
305        Subject s = createSubject();
306
307        // combine
308        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
309
310        ProtectionDomain[] r_pd = c.combine(current_pd, assigned_pd);
311        if(DEBUG) {
312            System.out.println("=========== c_pd");
313            dumpPD(current_pd);
314            System.out.println("=========== a_pd");
315            dumpPD(assigned_pd);
316            System.out.println("=========== r_pd");
317            dumpPD(r_pd);
318            System.out.println("===========");
319        }
320
321        for(int i = 0; i < r_pd.length; i++) {
322            ProtectionDomain pd = r_pd[i];
323            // check CodeSource
324            assertTrue("code source mismatch", pd.getCodeSource().equals(cs));
325
326            // check ClassLoader
327            assertTrue("class loader mismatch", pd.getClassLoader().equals(current_pd_cl));
328
329            // check principals
330            Principal[] principals = pd.getPrincipals();
331
332            for(int j = 0; j < principals.length; j++) {
333                if(contains(SubjectX500names, principals[j].getName()) == false)
334                    fail("principal mismatch ("  + j +") " + principals[j].getName());
335            }
336
337            // check permissions
338            PermissionCollection perms = pd.getPermissions();
339
340            Enumeration<Permission> p = perms.elements();
341            while(p.hasMoreElements()) {
342                Permission pp = p.nextElement();
343
344                String pn = pp.getName();
345
346                   if(contains(currentDomainPerms, pn) == false)
347                       fail("current domains permissions mismatch " + pn);
348            }
349        }
350    }
351
352    /**
353     * @tests javax.security.auth.SubjectDomainCombiner#combine()
354     */
355    @TestTargetNew(
356        level = TestLevel.COMPLETE,
357        notes = "currentDomains is null",
358        method = "combine",
359        args = {ProtectionDomain[].class, ProtectionDomain[].class}
360    )
361    public void test_combine_03() {
362
363        URL url;
364        try {
365            url = new URL(locationUrl);
366        } catch (MalformedURLException mue) {
367            throw new Error(mue);
368        }
369        CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null);
370
371        class MyClassLoader extends ClassLoader {
372            public MyClassLoader() {
373                super();
374            }
375        }
376
377        ClassLoader current_pd_cl = new MyClassLoader() ;
378        ClassLoader assigned_pd_cl = new MyClassLoader() ;
379
380        // current domains
381        ProtectionDomain[] current_pd = null;
382
383        // assigned domains
384        ProtectionDomain[] assigned_pd = createProtectionDomains(cs, assigned_pd_cl, assignedDomainX500names, assignedDomainPerms);
385
386        // subject
387        Subject s = createSubject();
388
389        // combine
390        SubjectDomainCombiner c = new SubjectDomainCombiner(s);
391
392        ProtectionDomain[] r_pd = c.combine(current_pd, assigned_pd);
393        if(DEBUG) {
394            System.out.println("=========== c_pd");
395            dumpPD(current_pd);
396            System.out.println("=========== a_pd");
397            dumpPD(assigned_pd);
398            System.out.println("=========== r_pd");
399            dumpPD(r_pd);
400            System.out.println("===========");
401        }
402
403        for(int i = 0; i < r_pd.length; i++) {
404            ProtectionDomain pd = r_pd[i];
405            // check CodeSource
406            assertTrue("code source mismatch", pd.getCodeSource().equals(cs));
407            // check ClassLoader
408            assertTrue("class loader mismatch", pd.getClassLoader().equals(assigned_pd_cl));
409
410            // check principals
411            Principal[] principals = pd.getPrincipals();
412            for(int j = 0; j < principals.length; j++) {
413                if(contains(assignedDomainX500names, principals[j].getName()) == false)
414                    fail("principal mismatch ("  + j +") " + principals[j].getName());
415            }
416
417            // check permissions
418            PermissionCollection perms = pd.getPermissions();
419
420            Enumeration<Permission> p = perms.elements();
421            while(p.hasMoreElements()) {
422                Permission pp = p.nextElement();
423
424                String pn = pp.getName();
425
426                  if(contains(assignedDomainPerms, pn) == false)
427                       fail("assigned domains permissions mismatch " + pn);
428            }
429        }
430    }
431
432    protected ProtectionDomain[] createProtectionDomains(CodeSource cs, ClassLoader cl, String[] names, String[] perms) {
433        ProtectionDomain[] pd = new ProtectionDomain[perms.length];
434        Principal[] principals = new Principal[names.length];
435        for(int i = 0; i < names.length; i++) {
436            principals[i] = new X500Principal(names[i]);
437        }
438        for(int i = 0; i < perms.length; i++) {
439            RuntimePermission rp = new RuntimePermission(perms[i]);
440            PermissionCollection pc = rp.newPermissionCollection();
441            pc.add(rp);
442            pd[i] = new ProtectionDomain(cs, pc, cl, principals);
443        }
444        return pd;
445    }
446
447    protected Subject createSubject() {
448        // principal
449        HashSet<Principal> principal_set = new HashSet<Principal>();
450        for(int i = 0; i < SubjectX500names.length; i++)
451            principal_set.add(new X500Principal(SubjectX500names[i]));
452
453        // public permissions
454        HashSet<Permission> pub_perms_set = new HashSet<Permission>();
455        pub_perms_set.add(new RuntimePermission(subjectPubPerm1));
456
457        // private permissions
458        HashSet<Permission> pvt_perms_set = new HashSet<Permission>();
459        pvt_perms_set.add(new RuntimePermission(subjectPvtPerm1));
460
461        Subject s = new Subject(false, principal_set, pub_perms_set, pvt_perms_set);
462        return s;
463    }
464
465    boolean contains(String[] arr, String val) {
466        for(int i = 0; i < arr.length; i++)
467            if(arr[i].compareTo(val) == 0)
468                return true;
469        return false;
470    }
471
472    private void dumpPD(ProtectionDomain[] arr) {
473        if(DEBUG) {
474            if(arr == null) return;
475            for(int i = 0; i < arr.length; i++) {
476                System.out.println(arr[i].getCodeSource().getLocation().toString());
477                dumpPerms(arr[i].getPermissions());
478                dumpPrincipals(arr[i].getPrincipals());
479            }
480        }
481    }
482
483    private void dumpPerms(PermissionCollection perms) {
484        if(DEBUG) {
485            Enumeration<Permission> p = perms.elements();
486            while(p.hasMoreElements()) {
487                Permission pp = p.nextElement();
488                System.out.println("   " + pp.getName() + "    " + pp.getActions());
489            }
490        }
491    }
492
493    private void dumpPrincipals(Principal[] p) {
494        if(DEBUG) {
495            if(p == null) return;
496            for(int i = 0; i < p.length; i++) {
497                System.out.println("   " + p[i].getName());
498            }
499        }
500    }
501
502}
503
504