blob: 178358b3125eba673569eb5b7901c1345fd2d3ee [file] [log] [blame]
Karl Pauls36407322008-03-07 00:37:30 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * 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,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.framework.security.permissionadmin;
20
21import java.io.IOException;
22import java.security.AllPermission;
23import java.security.Permission;
24import java.security.ProtectionDomain;
25import java.util.ArrayList;
26import java.util.HashMap;
27import java.util.List;
28import java.util.Map;
29
30import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
31import org.apache.felix.framework.security.util.Permissions;
32import org.apache.felix.framework.security.util.PropertiesCache;
Karl Pauls23287bd2010-01-10 22:11:27 +000033import org.apache.felix.moduleloader.IContent;
Karl Pauls36407322008-03-07 00:37:30 +000034import org.osgi.framework.Bundle;
35import org.osgi.service.permissionadmin.PermissionAdmin;
36import org.osgi.service.permissionadmin.PermissionInfo;
37
38/**
Karl Pauls23287bd2010-01-10 22:11:27 +000039 * This class is a relatively straight forward implementation of the
40 * PermissionAdmin service. The only somewhat involved thing is that it respects
41 * the presents of a conditionalpermissionadmin service as per spec.
Karl Pauls36407322008-03-07 00:37:30 +000042 */
Karl Pauls23287bd2010-01-10 22:11:27 +000043// TODO: Do we need this class at all or can we just emulate it using the
44// condpermadmin?
Karl Pauls36407322008-03-07 00:37:30 +000045public final class PermissionAdminImpl implements PermissionAdmin
46{
Karl Pauls23287bd2010-01-10 22:11:27 +000047 private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
48 AllPermission.class.getName(), "", "") };
49
Karl Pauls36407322008-03-07 00:37:30 +000050 private final Map m_store = new HashMap();
51
52 private final PropertiesCache m_cache;
53
54 private final Permissions m_permissions;
55
56 private PermissionInfo[] m_default = null;
57
58 public PermissionAdminImpl(Permissions permissions, PropertiesCache cache)
59 throws IOException
60 {
61 m_permissions = permissions;
62 m_cache = cache;
Karl Pauls23287bd2010-01-10 22:11:27 +000063 m_cache.read(PermissionInfo[].class, m_store);
Karl Pauls36407322008-03-07 00:37:30 +000064 }
65
66 public PermissionInfo[] getDefaultPermissions()
67 {
68 synchronized (m_store)
69 {
70 if (m_default == null)
71 {
72 return null;
73 }
74 return (PermissionInfo[]) m_default.clone();
75 }
76 }
77
78 public synchronized String[] getLocations()
79 {
80 synchronized (m_store)
81 {
82 if (m_store.isEmpty())
83 {
84 return null;
85 }
86
87 return (String[]) m_store.keySet().toArray(
88 new String[m_store.size()]);
89 }
90 }
91
92 public PermissionInfo[] getPermissions(String location)
93 {
94 synchronized (m_store)
95 {
96 if (m_store.containsKey(location))
97 {
98 return (PermissionInfo[]) ((PermissionInfo[]) m_store
99 .get(location)).clone();
100 }
101 return null;
102 }
103 }
104
105 /**
Karl Pauls23287bd2010-01-10 22:11:27 +0000106 * This will do the actual permission check as described in the core spec
107 * 10.2 It will respect a present condpermadmin service as described in
108 * 9.10.
Karl Pauls36407322008-03-07 00:37:30 +0000109 *
Karl Pauls23287bd2010-01-10 22:11:27 +0000110 * @param location
111 * the location of the bundle.
112 * @param bundle
113 * the bundle in question.
114 * @param permission
115 * the permission to check.
116 * @param cpai
117 * A condpermadmin if one is present else null.
118 * @param pd
119 * the protectiondomain
120 * @return Boolean.TRUE if the location is bound and the permission is
121 * granted or if there is no cpa and the default permissions imply
122 * the permission Boolean.FALSE otherwise unless the location is not
123 * bound and their is a cpa in which case null is returned.
Karl Pauls36407322008-03-07 00:37:30 +0000124 */
125 public Boolean hasPermission(String location, Bundle bundle,
126 Permission permission, ConditionalPermissionAdminImpl cpai,
Karl Pauls23287bd2010-01-10 22:11:27 +0000127 ProtectionDomain pd, IContent content)
Karl Pauls36407322008-03-07 00:37:30 +0000128 {
129 PermissionInfo[] permissions = null;
Karl Pauls23287bd2010-01-10 22:11:27 +0000130 PermissionInfo[] defaults = null;
131 boolean contains = false;
Karl Pauls36407322008-03-07 00:37:30 +0000132 synchronized (m_store)
133 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000134 contains = m_store.containsKey(location);
135 permissions = (PermissionInfo[]) m_store.get(location);
136 defaults = m_default;
Karl Pauls36407322008-03-07 00:37:30 +0000137 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000138 if (contains)
Karl Pauls36407322008-03-07 00:37:30 +0000139 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000140 if (check(permissions, permission, bundle))
141 {
142 return Boolean.TRUE;
143 }
144 return check(m_permissions.getImplicit(bundle), permission, bundle) ? Boolean.TRUE
145 : Boolean.FALSE;
146 }
147 else if (cpai == null
148 || (cpai.isEmpty() && cpai
149 .impliesLocal(bundle, content, permission)))
150 {
151 if (defaults != null)
152 {
153 if (check(defaults, permission, null))
154 {
155 return Boolean.TRUE;
156 }
157 return check(m_permissions.getImplicit(bundle), permission,
158 bundle) ? Boolean.TRUE : Boolean.FALSE;
159 }
160 else
Karl Pauls36407322008-03-07 00:37:30 +0000161 {
162 return Boolean.TRUE;
163 }
164 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000165 else
Karl Pauls36407322008-03-07 00:37:30 +0000166 {
167 return null;
168 }
Karl Pauls36407322008-03-07 00:37:30 +0000169 }
170
171 private boolean check(PermissionInfo[] permissions, Permission permission,
172 Bundle bundle)
173 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000174 Permissions permissionsObject = m_permissions
175 .getPermissions(permissions);
Karl Pauls36407322008-03-07 00:37:30 +0000176
177 return permissionsObject.implies(permission, bundle);
178 }
179
180 public void setDefaultPermissions(PermissionInfo[] permissions)
181 {
182 Object sm = System.getSecurityManager();
183 if (sm != null)
184 {
185 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
186 }
187
188 synchronized (m_cache)
189 {
190 PermissionInfo[] def = null;
191 Map store = null;
192 synchronized (m_store)
193 {
194 def = m_default;
195 store = new HashMap(m_store);
196
197 m_default = (permissions != null) ? notNull(permissions) : null;
198 }
199
200 try
201 {
202 m_cache.write(setDefaults(store, def));
203 }
204 catch (IOException ex)
205 {
206 synchronized (m_store)
207 {
208 m_default = def;
209 }
210
211 ex.printStackTrace();
212 // TODO: log this
213 throw new IllegalStateException(ex.getMessage());
214 }
215 }
216 }
217
218 public void setPermissions(String location, PermissionInfo[] permissions)
219 {
220 Object sm = System.getSecurityManager();
221 if (sm != null)
222 {
223 ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
224 }
225
226 synchronized (m_cache)
227 {
228 if (location != null)
229 {
230 Map store = null;
231 Map storeCopy = null;
232 PermissionInfo[] def = null;
233 synchronized (m_store)
234 {
235 storeCopy = new HashMap(m_store);
236 if (permissions != null)
237 {
238 m_store.put(location, notNull(permissions));
239 }
240 else
241 {
242 m_store.remove(location);
243 }
244 store = new HashMap(m_store);
245 }
246 try
247 {
248 m_cache.write(setDefaults(store, def));
249 }
250 catch (IOException ex)
251 {
252 synchronized (m_store)
253 {
254 m_store.clear();
255 m_store.putAll(storeCopy);
256 }
257
258 ex.printStackTrace();
259 // TODO: log this
260 throw new IllegalStateException(ex.getMessage());
261 }
262 }
263 }
264 }
265
266 private Map setDefaults(Map store, PermissionInfo[] def)
267 {
268 if (def != null)
269 {
270 store.put("DEFAULT", def);
271 }
272 else
273 {
274 store.remove("DEFAULT");
275 }
276 return store;
277 }
278
279 private PermissionInfo[] notNull(PermissionInfo[] permissions)
280 {
281 List result = new ArrayList();
282
283 for (int i = 0; i < permissions.length; i++)
284 {
285 if (permissions[i] != null)
286 {
287 result.add(permissions[i]);
288 }
289 }
290 return (PermissionInfo[]) result.toArray(new PermissionInfo[result
291 .size()]);
292 }
293}