Fixing a few bugs in the statistics printout.
[jpf-core.git] / src / classes / java / security / ProtectionDomain.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package java.security;
19
20 import java.util.ArrayList;
21 import java.util.Enumeration;
22 import java.util.List;
23 import sun.security.util.Debug;
24 import sun.security.util.SecurityConstants;
25
26 // TODO: Fix for Groovy's model-checking
27 // TODO: This model class is a placeholder for future implementation
28 /**
29  * MJI model class for java.security.ProtectionDomain library abstraction
30  */
31 public class ProtectionDomain {
32
33     private CodeSource codesource ;
34
35     private ClassLoader classloader;
36
37     private Principal[] principals;
38
39     private PermissionCollection permissions;
40
41     private boolean hasAllPerm = false;
42
43     private boolean staticPermissions;
44
45     final Key key = new Key();
46
47     private Debug debug = Debug.getInstance("domain");
48
49     public ProtectionDomain(CodeSource codesource,
50                             PermissionCollection permissions) {
51         this.codesource = codesource;
52         if (permissions != null) {
53             this.permissions = permissions;
54             this.permissions.setReadOnly();
55             if (permissions instanceof Permissions &&
56                     ((Permissions)permissions).allPermission != null) {
57                 hasAllPerm = true;
58             }
59         }
60         this.classloader = null;
61         this.principals = new Principal[0];
62         staticPermissions = true;
63     }
64
65     public ProtectionDomain(CodeSource codesource,
66                             PermissionCollection permissions,
67                             ClassLoader classloader,
68                             Principal[] principals) {
69         this.codesource = codesource;
70         if (permissions != null) {
71             this.permissions = permissions;
72             this.permissions.setReadOnly();
73             if (permissions instanceof Permissions &&
74                     ((Permissions)permissions).allPermission != null) {
75                 hasAllPerm = true;
76             }
77         }
78         this.classloader = classloader;
79         this.principals = (principals != null ? principals.clone():
80                 new Principal[0]);
81         staticPermissions = false;
82     }
83
84     public final CodeSource getCodeSource() {
85         return this.codesource;
86     }
87
88     public final ClassLoader getClassLoader() {
89         return this.classloader;
90     }
91
92     public final Principal[] getPrincipals() {
93         return this.principals.clone();
94     }
95
96     public final PermissionCollection getPermissions() {
97         return permissions;
98     }
99
100     public boolean implies(Permission permission) {
101
102         if (hasAllPerm) {
103             // internal permission collection already has AllPermission -
104             // no need to go to policy
105             return true;
106         }
107
108         if (!staticPermissions &&
109                 Policy.getPolicyNoCheck().implies(this, permission))
110             return true;
111         if (permissions != null)
112             return permissions.implies(permission);
113
114         return false;
115     }
116
117     boolean impliesCreateAccessControlContext() {
118         return implies(SecurityConstants.CREATE_ACC_PERMISSION);
119     }
120
121     @Override public String toString() {
122         String pals = "<no principals>";
123         if (principals != null && principals.length > 0) {
124             StringBuilder palBuf = new StringBuilder("(principals ");
125
126             for (int i = 0; i < principals.length; i++) {
127                 palBuf.append(principals[i].getClass().getName() +
128                         " \"" + principals[i].getName() +
129                         "\"");
130                 if (i < principals.length-1)
131                     palBuf.append(",\n");
132                 else
133                     palBuf.append(")\n");
134             }
135             pals = palBuf.toString();
136         }
137
138         // Check if policy is set; we don't want to load
139         // the policy prematurely here
140         PermissionCollection pc = Policy.isSet() && seeAllp() ?
141                 mergePermissions():
142                 getPermissions();
143
144         return "ProtectionDomain "+
145                 " "+codesource+"\n"+
146                 " "+classloader+"\n"+
147                 " "+pals+"\n"+
148                 " "+pc+"\n";
149     }
150
151     private boolean seeAllp() {
152         SecurityManager sm = System.getSecurityManager();
153
154         if (sm == null) {
155             return true;
156         } else {
157             if (debug != null) {
158                 if (sm.getClass().getClassLoader() == null &&
159                         Policy.getPolicyNoCheck().getClass().getClassLoader()
160                                 == null) {
161                     return true;
162                 }
163             } else {
164                 try {
165                     sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
166                     return true;
167                 } catch (SecurityException se) {
168                     // fall thru and return false
169                 }
170             }
171         }
172
173         return false;
174     }
175
176     private PermissionCollection mergePermissions() {
177         if (staticPermissions)
178             return permissions;
179
180         PermissionCollection perms =
181                 java.security.AccessController.doPrivileged
182                         (new java.security.PrivilegedAction<PermissionCollection>() {
183                             public PermissionCollection run() {
184                                 Policy p = Policy.getPolicyNoCheck();
185                                 return p.getPermissions(ProtectionDomain.this);
186                             }
187                         });
188
189         Permissions mergedPerms = new Permissions();
190         int swag = 32;
191         int vcap = 8;
192         Enumeration<Permission> e;
193         List<Permission> pdVector = new ArrayList<>(vcap);
194         List<Permission> plVector = new ArrayList<>(swag);
195
196         //
197         // Build a vector of domain permissions for subsequent merge
198         if (permissions != null) {
199             synchronized (permissions) {
200                 e = permissions.elements();
201                 while (e.hasMoreElements()) {
202                     pdVector.add(e.nextElement());
203                 }
204             }
205         }
206
207         //
208         // Build a vector of Policy permissions for subsequent merge
209         if (perms != null) {
210             synchronized (perms) {
211                 e = perms.elements();
212                 while (e.hasMoreElements()) {
213                     plVector.add(e.nextElement());
214                     vcap++;
215                 }
216             }
217         }
218
219         if (perms != null && permissions != null) {
220             //
221             // Weed out the duplicates from the policy. Unless a refresh
222             // has occurred since the pd was consed this should result in
223             // an empty vector.
224             synchronized (permissions) {
225                 e = permissions.elements();   // domain vs policy
226                 while (e.hasMoreElements()) {
227                     Permission pdp = e.nextElement();
228                     Class<?> pdpClass = pdp.getClass();
229                     String pdpActions = pdp.getActions();
230                     String pdpName = pdp.getName();
231                     for (int i = 0; i < plVector.size(); i++) {
232                         Permission pp = plVector.get(i);
233                         if (pdpClass.isInstance(pp)) {
234                             // The equals() method on some permissions
235                             // have some side effects so this manual
236                             // comparison is sufficient.
237                             if (pdpName.equals(pp.getName()) &&
238                                     pdpActions.equals(pp.getActions())) {
239                                 plVector.remove(i);
240                                 break;
241                             }
242                         }
243                     }
244                 }
245             }
246         }
247
248         if (perms !=null) {
249             // the order of adding to merged perms and permissions
250             // needs to preserve the bugfix 4301064
251
252             for (int i = plVector.size()-1; i >= 0; i--) {
253                 mergedPerms.add(plVector.get(i));
254             }
255         }
256         if (permissions != null) {
257             for (int i = pdVector.size()-1; i >= 0; i--) {
258                 mergedPerms.add(pdVector.get(i));
259             }
260         }
261
262         return mergedPerms;
263     }
264
265     final class Key {}
266 }