/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.felix.framework.security.permissionadmin; import java.io.IOException; import java.security.AllPermission; import java.security.Permission; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl; import org.apache.felix.framework.security.util.Permissions; import org.apache.felix.framework.security.util.PropertiesCache; //import org.apache.felix.moduleloader.IContent; import org.apache.felix.framework.cache.Content; import org.osgi.framework.Bundle; import org.osgi.service.permissionadmin.PermissionAdmin; import org.osgi.service.permissionadmin.PermissionInfo; /** * This class is a relatively straight forward implementation of the * PermissionAdmin service. The only somewhat involved thing is that it respects * the presents of a conditionalpermissionadmin service as per spec. */ // TODO: Do we need this class at all or can we just emulate it using the // condpermadmin? public final class PermissionAdminImpl implements PermissionAdmin { private static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo( AllPermission.class.getName(), "", "") }; private final Map m_store = new HashMap(); private final PropertiesCache m_cache; private final Permissions m_permissions; private PermissionInfo[] m_default = null; public PermissionAdminImpl(Permissions permissions, PropertiesCache cache) throws IOException { m_permissions = permissions; m_cache = cache; m_cache.read(PermissionInfo[].class, m_store); } public PermissionInfo[] getDefaultPermissions() { synchronized (m_store) { if (m_default == null) { return null; } return (PermissionInfo[]) m_default.clone(); } } public synchronized String[] getLocations() { synchronized (m_store) { if (m_store.isEmpty()) { return null; } return (String[]) m_store.keySet().toArray( new String[m_store.size()]); } } public PermissionInfo[] getPermissions(String location) { synchronized (m_store) { if (m_store.containsKey(location)) { return (PermissionInfo[]) ((PermissionInfo[]) m_store .get(location)).clone(); } return null; } } /** * This will do the actual permission check as described in the core spec * 10.2 It will respect a present condpermadmin service as described in * 9.10. * * @param location * the location of the bundle. * @param bundle * the bundle in question. * @param permission * the permission to check. * @param cpai * A condpermadmin if one is present else null. * @param pd * the protectiondomain * @return Boolean.TRUE if the location is bound and the permission is * granted or if there is no cpa and the default permissions imply * the permission Boolean.FALSE otherwise unless the location is not * bound and their is a cpa in which case null is returned. */ public Boolean hasPermission(String location, Bundle bundle, Permission permission, ConditionalPermissionAdminImpl cpai, ProtectionDomain pd, Content content) { PermissionInfo[] permissions = null; PermissionInfo[] defaults = null; boolean contains = false; synchronized (m_store) { contains = m_store.containsKey(location); permissions = (PermissionInfo[]) m_store.get(location); defaults = m_default; } if (contains) { if (check(permissions, permission, bundle)) { return Boolean.TRUE; } return check(m_permissions.getImplicit(bundle), permission, bundle) ? Boolean.TRUE : Boolean.FALSE; } else if (cpai == null || (cpai.isEmpty() && cpai .impliesLocal(bundle, content, permission))) { if (defaults != null) { if (check(defaults, permission, null)) { return Boolean.TRUE; } return check(m_permissions.getImplicit(bundle), permission, bundle) ? Boolean.TRUE : Boolean.FALSE; } else { return Boolean.TRUE; } } else { return null; } } private boolean check(PermissionInfo[] permissions, Permission permission, Bundle bundle) { Permissions permissionsObject = m_permissions .getPermissions(permissions); return permissionsObject.implies(permission, bundle); } public void setDefaultPermissions(PermissionInfo[] permissions) { Object sm = System.getSecurityManager(); if (sm != null) { ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION); } synchronized (m_cache) { PermissionInfo[] def = null; Map store = null; synchronized (m_store) { def = m_default; store = new HashMap(m_store); m_default = (permissions != null) ? notNull(permissions) : null; } try { m_cache.write(setDefaults(store, def)); } catch (IOException ex) { synchronized (m_store) { m_default = def; } ex.printStackTrace(); // TODO: log this throw new IllegalStateException(ex.getMessage()); } } } public void setPermissions(String location, PermissionInfo[] permissions) { Object sm = System.getSecurityManager(); if (sm != null) { ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION); } synchronized (m_cache) { if (location != null) { Map store = null; Map storeCopy = null; PermissionInfo[] def = null; synchronized (m_store) { storeCopy = new HashMap(m_store); if (permissions != null) { m_store.put(location, notNull(permissions)); } else { m_store.remove(location); } store = new HashMap(m_store); } try { m_cache.write(setDefaults(store, def)); } catch (IOException ex) { synchronized (m_store) { m_store.clear(); m_store.putAll(storeCopy); } ex.printStackTrace(); // TODO: log this throw new IllegalStateException(ex.getMessage()); } } } } private Map setDefaults(Map store, PermissionInfo[] def) { if (def != null) { store.put("DEFAULT", def); } else { store.remove("DEFAULT"); } return store; } private PermissionInfo[] notNull(PermissionInfo[] permissions) { List result = new ArrayList(); for (int i = 0; i < permissions.length; i++) { if (permissions[i] != null) { result.add(permissions[i]); } } return (PermissionInfo[]) result.toArray(new PermissionInfo[result .size()]); } }