You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2010/01/10 23:11:28 UTC
svn commit: r897721 [1/2] - in /felix/trunk/framework.security: ./
src/main/java/org/apache/felix/framework/
src/main/java/org/apache/felix/framework/security/
src/main/java/org/apache/felix/framework/security/condpermadmin/
src/main/java/org/apache/fe...
Author: pauls
Date: Sun Jan 10 22:11:27 2010
New Revision: 897721
URL: http://svn.apache.org/viewvc?rev=897721&view=rev
Log:
Add support for the 4.2.0 security specifications. This includes implementations of the access flag and various other changes (FELIX-1904, FELIX-22).
Removed:
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SignerMatcher.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/verifier/SubjectDNParser.java
felix/trunk/framework.security/src/main/java/org/osgi/service/condpermadmin/
Modified:
felix/trunk/framework.security/pom.xml
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/Conditions.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/LocalPermissions.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/Permissions.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/PropertiesCache.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/TrustManager.java
felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/verifier/BundleDNParser.java
Modified: felix/trunk/framework.security/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/pom.xml?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/pom.xml (original)
+++ felix/trunk/framework.security/pom.xml Sun Jan 10 22:11:27 2010
@@ -34,7 +34,7 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>4.1.0</version>
+ <version>4.2.0</version>
</dependency>
<dependency>
<groupId>${pom.groupId}</groupId>
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityActivator.java Sun Jan 10 22:11:27 2010
@@ -20,12 +20,9 @@
import java.io.File;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
import java.util.StringTokenizer;
-import java.util.Map.Entry;
+import org.apache.felix.framework.ext.SecurityProvider;
import org.apache.felix.framework.security.SecurityConstants;
import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
@@ -33,81 +30,72 @@
import org.apache.felix.framework.security.util.LocalPermissions;
import org.apache.felix.framework.security.util.Permissions;
import org.apache.felix.framework.security.util.PropertiesCache;
-import org.apache.felix.framework.security.verifier.BundleDNParser;
import org.apache.felix.framework.util.SecureAction;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
import org.osgi.service.permissionadmin.PermissionAdmin;
/**
- * <p>This Felix specific activator installs a security provider with the Felix
+ * <p>
+ * This Felix specific activator installs a security provider with the Felix
* framework. The security settings can be changed via the
- * {@link PermissionAdmin} and/or the
- * {@link ConditionalPermissionAdmin} services that may be published by
- * this class.
+ * {@link PermissionAdmin} and/or the {@link ConditionalPermissionAdmin}
+ * services that may be published by this class.
* </p>
* <p>
- * Permission informations as well as caching data will be stored in several
- * files in a directory called <tt>security</tt> obtained by a call to
+ * Permission informations as well as caching data will be stored in several
+ * files in a directory called <tt>security</tt> obtained by a call to
* {@link BundleContext#getDataFile(String))}.
* </p>
* <p>
* The following properties are recognized:
* <p>
- * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not
- * (<tt>true</tt>|<tt>false</tt>) to
- * publish a{@link ConditionalPermissionAdmin} service. The default is
+ * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not (
+ * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
+ * service. The default is
* {@link SecurityConstants#ENABLE_PERMISSIONADMIN_VALUE}.
* </p>
* <p>
- * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not
- * (<tt>true</tt>|<tt>false</tt>) to
- * publish a{@link ConditionalPermissionAdmin} service. The default is
- * {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
+ * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not (
+ * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
+ * service. The default is {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
* </p>
* <p>
* {@link SecurityConstants#KEYSTORE_FILE_PROP} - The keystore URL(s) to use as
* trusted CA stores. The urls must be separated by a guard (i.e., <tt>|</tt>).
- * The default is
- * {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
+ * The default is {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
* </p>
* <p>
* {@link SecurityConstants#KEYSTORE_PASS_PROP} - The keystore password(s) to
- * use for the given keystores. The passwords must be separated by a guard
+ * use for the given keystores. The passwords must be separated by a guard
* (i.e., <tt>|</tt>).The default is
* {@link SecurityConstants#KEYSTORE_PASS_VALUE}.
* </p>
* <p>
* {@link SecurityConstants#KEYSTORE_TYPE_PROP} - The keystore type(s) to use
- * for the given keystores. The types must be separated by a guard
- * (i.e., <tt>|</tt>).The default is
- * {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
+ * for the given keystores. The types must be separated by a guard (i.e.,
+ * <tt>|</tt>).The default is {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
* </p>
* <p>
* {@link SecurityConstants#CRL_FILE_PROP} - The CRL URL(s) to use for revoked
- * certificates. The urls must be separated by a guard (i.e., <tt>|</tt>).
- * The default is {@link SecurityConstants#CRL_FILE_VALUE}.
+ * certificates. The urls must be separated by a guard (i.e., <tt>|</tt>). The
+ * default is {@link SecurityConstants#CRL_FILE_VALUE}.
* </p>
* </p>
*/
/*
* TODO: using a string for passwords is bad. We need to investigate
- * alternatives.
+ * alternatives.
*
- * TODO: we might want to allow for the recognized properties to
- * change without a restart. This is trick because we can not publish a managed
- * service due to not being able to import as we are an extension bundle.
+ * TODO: we might want to allow for the recognized properties to change without
+ * a restart. This is trick because we can not publish a managed service due to
+ * not being able to import as we are an extension bundle.
*/
public final class SecurityActivator implements BundleActivator
{
- private SecurityProviderImpl m_provider = null;
- private PropertiesCache m_dnsCache = null;
- private PropertiesCache m_localCache = null;
- private LocalPermissions m_localPermissions = null;
-
public synchronized void start(BundleContext context) throws Exception
{
PermissionAdminImpl pai = null;
@@ -135,15 +123,14 @@
SecurityConstants.ENABLE_PERMISSIONADMIN_PROP,
SecurityConstants.ENABLE_PERMISSIONADMIN_VALUE)))
{
- File cache =
- context.getDataFile("security" + File.separator + "pa.txt");
+ File cache = context.getDataFile("security" + File.separator
+ + "pa.txt");
if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
{
throw new IOException("Can't create cache file");
}
- pai =
- new PermissionAdminImpl(permissions, new PropertiesCache(cache,
- tmp, action));
+ pai = new PermissionAdminImpl(permissions, new PropertiesCache(
+ cache, tmp, action));
}
ConditionalPermissionAdminImpl cpai = null;
@@ -152,92 +139,72 @@
SecurityConstants.ENABLE_CONDPERMADMIN_PROP,
SecurityConstants.ENABLE_CONDPERMADMIN_VALUE)))
{
- File cpaCache =
- context.getDataFile("security" + File.separator + "cpa.txt");
- if ((cpaCache == null) || (!cpaCache.isFile() && !cpaCache.createNewFile()))
- {
- throw new IOException("Can't create cache file");
- }
- File localCache =
- context.getDataFile("security" + File.separator + "local.txt");
- if ((localCache == null) || (!localCache.isFile() && !localCache.createNewFile()))
+ File cpaCache = context.getDataFile("security" + File.separator
+ + "cpa.txt");
+ if ((cpaCache == null)
+ || (!cpaCache.isFile() && !cpaCache.createNewFile()))
{
throw new IOException("Can't create cache file");
}
-
- m_localCache = new PropertiesCache(localCache, tmp, action);
- m_localPermissions = new LocalPermissions(permissions, m_localCache);
-
- cpai =
- new ConditionalPermissionAdminImpl(permissions, new Conditions(
- action), m_localPermissions,
- new PropertiesCache(cpaCache, tmp, action));
+
+ LocalPermissions localPermissions = new LocalPermissions(
+ permissions);
+
+ cpai = new ConditionalPermissionAdminImpl(permissions,
+ new Conditions(action), localPermissions, new PropertiesCache(
+ cpaCache, tmp, action), pai);
}
if ((pai != null) || (cpai != null))
{
- String crlList =
- getProperty(context, SecurityConstants.CRL_FILE_PROP,
- SecurityConstants.CRL_FILE_VALUE);
- String storeList =
- getProperty(context, SecurityConstants.KEYSTORE_FILE_PROP,
- SecurityConstants.KEYSTORE_FILE_VALUE);
- String passwdList =
- getProperty(context, SecurityConstants.KEYSTORE_PASS_PROP,
- SecurityConstants.KEYSTORE_PASS_VALUE);
- String typeList =
- getProperty(context, SecurityConstants.KEYSTORE_TYPE_PROP,
- SecurityConstants.KEYSTORE_TYPE_VALUE);
+ String crlList = getProperty(context,
+ SecurityConstants.CRL_FILE_PROP,
+ SecurityConstants.CRL_FILE_VALUE);
+ String storeList = getProperty(context,
+ SecurityConstants.KEYSTORE_FILE_PROP,
+ SecurityConstants.KEYSTORE_FILE_VALUE);
+ String passwdList = getProperty(context,
+ SecurityConstants.KEYSTORE_PASS_PROP,
+ SecurityConstants.KEYSTORE_PASS_VALUE);
+ String typeList = getProperty(context,
+ SecurityConstants.KEYSTORE_TYPE_PROP,
+ SecurityConstants.KEYSTORE_TYPE_VALUE);
+ String osgi_keystores = getProperty(context,
+ Constants.FRAMEWORK_TRUST_REPOSITORIES, null);
+ if (osgi_keystores != null)
+ {
+ StringTokenizer tok = new StringTokenizer(osgi_keystores,
+ File.pathSeparator);
+
+ if (storeList.length() == 0)
+ {
+ storeList += "file:" + tok.nextToken();
+ passwdList += " ";
+ typeList += "JKS";
+ }
+ while (tok.hasMoreTokens())
+ {
+ storeList += "|file:" + tok.nextToken();
+ passwdList += "| ";
+ typeList += "|JKS";
+ }
+ }
StringTokenizer storeTok = new StringTokenizer(storeList, "|");
StringTokenizer passwdTok = new StringTokenizer(passwdList, "|");
StringTokenizer typeTok = new StringTokenizer(typeList, "|");
- if ((storeTok.countTokens() != passwdTok.countTokens())
- || (passwdTok.countTokens() != typeTok.countTokens()))
+ if ((storeTok.countTokens() != typeTok.countTokens())
+ || (passwdTok.countTokens() != storeTok.countTokens()))
{
throw new BundleException(
"Each CACerts keystore must have one type and one passwd entry and vice versa.");
}
- m_provider =
- new SecurityProviderImpl(crlList, typeList, passwdList,
- storeList, pai, cpai, action);
-
- File cache =
- context.getDataFile("security" + File.separator + "dns.txt");
- if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
- {
- throw new IOException("Can't create cache file");
- }
- m_dnsCache = new PropertiesCache(cache, tmp, action);
-
- Map store = m_dnsCache.read(String[].class);
-
- if (store != null)
- {
- BundleDNParser parser = m_provider.getParser();
+ SecurityProvider provider = new SecurityProviderImpl(crlList,
+ typeList, passwdList, storeList, pai, cpai, action);
- for (Iterator iter = store.entrySet().iterator(); iter
- .hasNext();)
- {
- Entry entry = (Entry) iter.next();
- String[] value = (String[]) entry.getValue();
- if ("none".equals(value[0]))
- {
- parser.put((String) entry.getKey(), null);
- }
- else if ("invalid".equals(value[0]))
- {
- parser.put((String) entry.getKey(), new String[0]);
- }
- else
- {
- parser.put((String) entry.getKey(), value);
- }
- }
- }
- ((Felix) context.getBundle(0)).setSecurityProvider(m_provider);
+ ((Felix) context.getBundle(0)).setSecurityProvider(provider);
}
if (pai != null)
@@ -254,59 +221,7 @@
public synchronized void stop(BundleContext context) throws Exception
{
- if (m_provider != null)
- {
- m_dnsCache.write(write(m_provider.getParser().getCache(), context));
- }
- if (m_localPermissions != null)
- {
- m_localCache.write(write(m_localPermissions.getStore(), context));
- }
- m_provider = null;
- m_dnsCache = null;
- m_localPermissions = null;
- }
-
- private Map write(Map cache, BundleContext context)
- {
- // Filter the cached dn chains and only store the latest for each
- // bundle. This is ok because the framework will prune old revisions
- // after a restart. The format is <id>-<timestamp>
- Map store = new HashMap();
- Map index = new HashMap();
- for (Iterator iter = cache.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
-
- String key = (String) entry.getKey();
- String id = key.substring(0, key.indexOf("-"));
- String time = key.substring(key.indexOf("-") + 1);
- Bundle bundle = context.getBundle(Long.parseLong(id));
- long timeLong = Long.parseLong(time);
- if ((bundle == null) ||
- (bundle.getLastModified() > timeLong))
- {
- continue;
- }
- String last = (String) index.get(id);
-
- if ((last == null)
- || (Long.parseLong(last) < timeLong))
- {
- index.put(id, time);
- Object[] dns = (Object[]) entry.getValue();
- store.remove(id + "-" + last);
- if ((dns != null) && (dns.length > 0))
- {
- store.put(key, dns);
- }
- else
- {
- store.put(key, (dns == null) ? new String[] {"none"} : new String[] {"invalid"});
- }
- }
- }
- return store;
+ ((Felix) context.getBundle(0)).setSecurityProvider(null);
}
private String getProperty(BundleContext context, String key,
@@ -314,7 +229,6 @@
{
String result = context.getProperty(key);
- return ((result != null) && (result.trim().length() > 0)) ? result
- : defaultValue;
+ return (result != null) ? result : defaultValue;
}
}
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/SecurityProviderImpl.java Sun Jan 10 22:11:27 2010
@@ -26,13 +26,13 @@
import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
import org.apache.felix.framework.security.util.TrustManager;
import org.apache.felix.framework.security.verifier.BundleDNParser;
-import org.apache.felix.framework.security.verifier.SignerMatcher;
import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.moduleloader.IModule;
import org.osgi.framework.Bundle;
/**
- * This class is the entry point to the security. It is used to determine whether
- * a given bundle is signed correctely and has permissions based on
+ * This class is the entry point to the security. It is used to determine
+ * whether a given bundle is signed correctely and has permissions based on
* PermissionAdmin or ConditionalPermissionAdmin.
*/
public final class SecurityProviderImpl implements SecurityProvider
@@ -42,69 +42,49 @@
private final ConditionalPermissionAdminImpl m_cpai;
private final SecureAction m_action;
- SecurityProviderImpl(String crlList, String typeList,
- String passwdList, String storeList, PermissionAdminImpl pai,
+ SecurityProviderImpl(String crlList, String typeList, String passwdList,
+ String storeList, PermissionAdminImpl pai,
ConditionalPermissionAdminImpl cpai, SecureAction action)
{
m_pai = pai;
m_cpai = cpai;
m_action = action;
- m_parser =
- new BundleDNParser(new TrustManager(crlList, typeList, passwdList,
- storeList, m_action));
- }
-
- BundleDNParser getParser()
- {
- return m_parser;
+ m_parser = new BundleDNParser(new TrustManager(crlList, typeList,
+ passwdList, storeList, m_action));
}
/**
- * If the given bundle is signed but can not be verified (e.g., missing files)
- * then throw an exception.
+ * If the given bundle is signed but can not be verified (e.g., missing
+ * files) then throw an exception.
*/
public void checkBundle(Bundle bundle) throws Exception
{
- m_parser.checkDNChains(
- (Long.toString(bundle.getBundleId()) + "-" + bundle.getLastModified()),
- ((BundleImpl) bundle).getCurrentModule().getContent());
+ IModule module = ((BundleImpl) bundle).getCurrentModule();
+ m_parser.checkDNChains(module, module.getContent(),
+ Bundle.SIGNERS_TRUSTED);
}
/**
* Get a signer matcher that can be used to match digital signed bundles.
*/
- public Object getSignerMatcher(final Bundle bundle)
+ public Object getSignerMatcher(final Bundle bundle, int signersType)
{
- return new SignerMatcher(Long.toString(bundle.getBundleId()),
- bundle.getLastModified(),
- ((BundleImpl) bundle).getCurrentModule().getContent(),
- m_parser);
+ IModule module = ((BundleImpl) bundle).getCurrentModule();
+ return m_parser.getDNChains(module, module.getContent(), signersType);
}
- ThreadLocal loopCheck = new ThreadLocal();
-
/**
- * If we have a permissionadmin then ask that one first and have it
- * decide in case there is a location bound. If not then either use its
- * default permission in case there is no conditional permission admin
- * or else ask that one.
+ * If we have a permissionadmin then ask that one first and have it decide
+ * in case there is a location bound. If not then either use its default
+ * permission in case there is no conditional permission admin or else ask
+ * that one.
*/
public boolean hasBundlePermission(ProtectionDomain bundleProtectionDomain,
Permission permission, boolean direct)
{
- if (loopCheck.get() != null)
- {
- return true;
- }
- else
- {
- loopCheck.set(this);
- }
- try
- {
- BundleProtectionDomain pd =
- (BundleProtectionDomain) bundleProtectionDomain;
+ BundleProtectionDomain pd = (BundleProtectionDomain) bundleProtectionDomain;
BundleImpl bundle = pd.getBundle();
+ IModule module = pd.getModule();
if (bundle.getBundleId() == 0)
{
@@ -116,13 +96,22 @@
Boolean result = null;
if (m_pai != null)
{
- result =
- m_pai.hasPermission(bundle.getLocation(), pd.getBundle(),
- permission, m_cpai, pd);
+ result = m_pai.hasPermission(bundle._getLocation(), pd.getBundle(),
+ permission, m_cpai, pd, bundle.getCurrentModule().getContent());
}
if (result != null)
{
+ if ((m_cpai != null) && !direct)
+ {
+ boolean allow = result.booleanValue();
+ if (!allow)
+ {
+ m_cpai.clearPD();
+ return false;
+ }
+ return m_cpai.handlePAHandle(pd);
+ }
return result.booleanValue();
}
@@ -130,10 +119,7 @@
{
try
{
- return m_cpai.hasPermission(bundle,
- bundle.getCurrentModule().getContent(),
- bundle.getBundleId() + "-" +
- bundle.getLastModified(),null, pd,
+ return m_cpai.hasPermission(module, module.getContent(), pd,
permission, direct, m_pai);
}
catch (Exception e)
@@ -144,8 +130,5 @@
}
return false;
- } finally {
- loopCheck.set(null);
- }
}
}
\ No newline at end of file
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/SecurityConstants.java Sun Jan 10 22:11:27 2010
@@ -18,38 +18,29 @@
*/
package org.apache.felix.framework.security;
-import java.io.File;
-
public interface SecurityConstants
{
public static final String KEYSTORE_FILE_PROP = "felix.keystore";
- public static final String KEYSTORE_FILE_VALUE = "file:" +
- System.getProperty("java.home") + File.separatorChar + "lib"
- + File.separatorChar + "security" + File.separatorChar + "cacerts"
- + "|file:" + System.getProperty("user.home") + File.separatorChar
- + ".keystore";
+ public static final String KEYSTORE_FILE_VALUE = "";
public static final String KEYSTORE_TYPE_PROP = "felix.keystore.type";
- public static final String KEYSTORE_TYPE_VALUE = "JKS" + "|" + "JKS";
+ public static final String KEYSTORE_TYPE_VALUE = "";
public static final String KEYSTORE_PASS_PROP = "felix.keystore.pass";
- public static final String KEYSTORE_PASS_VALUE =
- "changeit" + "|" + "changeit";
+ public static final String KEYSTORE_PASS_VALUE = "";
public static final String CRL_FILE_PROP = "felix.crl";
public static final String CRL_FILE_VALUE = "";
- public static final String ENABLE_CONDPERMADMIN_PROP =
- "felix.security.conpermadmin";
+ public static final String ENABLE_CONDPERMADMIN_PROP = "felix.security.conpermadmin";
public static final String ENABLE_CONDPERMADMIN_VALUE = "true";
- public static final String ENABLE_PERMISSIONADMIN_PROP =
- "felix.security.permissionadmin";
+ public static final String ENABLE_PERMISSIONADMIN_PROP = "felix.security.permissionadmin";
public static final String ENABLE_PERMISSIONADMIN_VALUE = "true";
}
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionAdminImpl.java Sun Jan 10 22:11:27 2010
@@ -19,70 +19,222 @@
package org.apache.felix.framework.security.condpermadmin;
import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URL;
import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.DomainCombiner;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
import java.security.Permission;
+import java.security.Principal;
import java.security.ProtectionDomain;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.X509Certificate;
+import java.util.AbstractSet;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
import java.util.Map.Entry;
+import org.apache.felix.framework.BundleProtectionDomain;
+import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
import org.apache.felix.framework.security.util.Conditions;
import org.apache.felix.framework.security.util.LocalPermissions;
import org.apache.felix.framework.security.util.Permissions;
import org.apache.felix.framework.security.util.PropertiesCache;
import org.apache.felix.framework.util.IteratorToEnumeration;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.moduleloader.ICapability;
import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IModule;
+import org.apache.felix.moduleloader.IRequirement;
+import org.apache.felix.moduleloader.IWire;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
import org.osgi.service.condpermadmin.ConditionInfo;
import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
+import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
import org.osgi.service.permissionadmin.PermissionInfo;
/**
* An implementation of the ConditionalPermissionAdmin service that doesn't need
* to have a framework specific security manager set. It use the DomainGripper
- * to know what bundleprotectiondomains are expected.
+ * to know what bundleprotectiondomains are expected.
*/
public final class ConditionalPermissionAdminImpl implements
ConditionalPermissionAdmin
{
+ private static class OrderedHashMap extends HashMap
+ {
+ private final List m_order = new ArrayList();
+
+ public Object put(Object key, Object value)
+ {
+ Object result = super.put(key, value);
+ if (result != value)
+ {
+ m_order.remove(key);
+ m_order.add(key);
+ }
+ return result;
+ };
+
+ public void putAll(Map map)
+ {
+ for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
+ {
+ Entry entry = (Entry) iter.next();
+ put(entry.getKey(), entry.getValue());
+ }
+ };
+
+ public Set keySet()
+ {
+ return new AbstractSet()
+ {
+ public Iterator iterator()
+ {
+ return m_order.iterator();
+ }
+
+ public int size()
+ {
+ return m_order.size();
+ }
+
+ };
+ };
+
+ public Set entrySet()
+ {
+ return new AbstractSet()
+ {
+
+ public Iterator iterator()
+ {
+ return new Iterator()
+ {
+ Iterator m_iter = m_order.iterator();
+
+ public boolean hasNext()
+ {
+ return m_iter.hasNext();
+ }
+
+ public Object next()
+ {
+ final Object key = m_iter.next();
+ return new Entry()
+ {
+
+ public Object getKey()
+ {
+ return key;
+ }
+
+ public Object getValue()
+ {
+ return get(key);
+ }
+
+ public Object setValue(Object arg0)
+ {
+ throw new IllegalStateException(
+ "Not Implemented");
+ }
+ };
+ }
+
+ public void remove()
+ {
+ throw new IllegalStateException("Not Implemented");
+ }
+
+ };
+ }
+
+ public int size()
+ {
+ return m_order.size();
+ }
+
+ };
+ };
+
+ public Collection values()
+ {
+ List result = new ArrayList();
+ for (Iterator iter = m_order.iterator(); iter.hasNext();)
+ {
+ result.add(super.get(iter.next()));
+ }
+ return result;
+ };
+
+ public Object remove(Object key)
+ {
+ Object result = super.remove(key);
+ if (result != null)
+ {
+ m_order.remove(key);
+ }
+ return result;
+ };
+
+ public void clear()
+ {
+ super.clear();
+ m_order.clear();
+ };
+ };
+
private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
- private final Map m_condPermInfos = new HashMap();
+ private final Map m_condPermInfos = new OrderedHashMap();
private final PropertiesCache m_propertiesCache;
private final Permissions m_permissions;
private final Conditions m_conditions;
private final LocalPermissions m_localPermissions;
+ private final PermissionAdminImpl m_pai;
public ConditionalPermissionAdminImpl(Permissions permissions,
Conditions condtions, LocalPermissions localPermissions,
- PropertiesCache cache) throws IOException
+ PropertiesCache cache, PermissionAdminImpl pai) throws IOException
{
m_propertiesCache = cache;
m_permissions = permissions;
m_conditions = condtions;
m_localPermissions = localPermissions;
+ Map old = new OrderedHashMap();
// Now try to restore the cache.
- Map old = m_propertiesCache.read(ConditionalPermissionInfoImpl.class);
- if (old != null)
+ m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
+ for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
{
- for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
- {
- Entry entry = (Entry) iter.next();
- String name = (String) entry.getKey();
- ConditionalPermissionInfoImpl cpi =
- ((ConditionalPermissionInfoImpl) entry.getValue());
- m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(
- name, cpi._getConditionInfos(), cpi._getPermissionInfos(),
- this));
- }
+ Entry entry = (Entry) iter.next();
+ String name = (String) entry.getKey();
+ ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
+ .getValue());
+ m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
+ cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
+ .isAllow()));
}
+ m_pai = pai;
}
public ConditionalPermissionInfo addConditionalPermissionInfo(
@@ -93,9 +245,8 @@
{
((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
}
- ConditionalPermissionInfoImpl result =
- new ConditionalPermissionInfoImpl(notNull(conditions),
- notNull(permissions), this);
+ ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
+ notNull(conditions), notNull(permissions), this, true);
return write(result.getName(), result);
}
@@ -109,7 +260,8 @@
synchronized (m_condPermInfos)
{
- tmp = new HashMap(m_condPermInfos);
+ tmp = new OrderedHashMap();
+ tmp.putAll(m_condPermInfos);
if ((name != null) && (cpi != null))
{
@@ -133,8 +285,11 @@
{
synchronized (m_condPermInfos)
{
- m_condPermInfos.clear();
- m_condPermInfos.putAll(tmp);
+ if (tmp != null)
+ {
+ m_condPermInfos.clear();
+ m_condPermInfos.putAll(tmp);
+ }
}
ex.printStackTrace();
throw new IllegalStateException(ex.getMessage());
@@ -146,28 +301,485 @@
}
}
- // TODO: this is pretty much untested so it might not work like this
- public AccessControlContext getAccessControlContext(String[] signers)
+ private static class FakeBundle implements Bundle
+ {
+ private final Map m_certs;
+
+ public FakeBundle(Map certs)
+ {
+ m_certs = Collections.unmodifiableMap(certs);
+ }
+
+ public Enumeration findEntries(String arg0, String arg1, boolean arg2)
+ {
+ return null;
+ }
+
+ public BundleContext getBundleContext()
+ {
+ return null;
+ }
+
+ public long getBundleId()
+ {
+ return -1;
+ }
+
+ public URL getEntry(String arg0)
+ {
+ return null;
+ }
+
+ public Enumeration getEntryPaths(String arg0)
+ {
+ return null;
+ }
+
+ public Dictionary getHeaders()
+ {
+ return new Hashtable();
+ }
+
+ public Dictionary getHeaders(String arg0)
+ {
+ return new Hashtable();
+ }
+
+ public long getLastModified()
+ {
+ return 0;
+ }
+
+ public String getLocation()
+ {
+ return "";
+ }
+
+ public ServiceReference[] getRegisteredServices()
+ {
+ return null;
+ }
+
+ public URL getResource(String arg0)
+ {
+ return null;
+ }
+
+ public Enumeration getResources(String arg0) throws IOException
+ {
+ return null;
+ }
+
+ public ServiceReference[] getServicesInUse()
+ {
+ return null;
+ }
+
+ public Map getSignerCertificates(int arg0)
+ {
+ return m_certs;
+ }
+
+ public int getState()
+ {
+ return Bundle.UNINSTALLED;
+ }
+
+ public String getSymbolicName()
+ {
+ return null;
+ }
+
+ public Version getVersion()
+ {
+ return Version.emptyVersion;
+ }
+
+ public boolean hasPermission(Object arg0)
+ {
+ return false;
+ }
+
+ public Class loadClass(String arg0) throws ClassNotFoundException
+ {
+ return null;
+ }
+
+ public void start() throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void start(int arg0) throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void stop() throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void stop(int arg0) throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void uninstall() throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void update() throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public void update(InputStream arg0) throws BundleException
+ {
+ throw new IllegalStateException();
+ }
+
+ public boolean equals(Object o)
+ {
+ return this == o;
+ }
+
+ public int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+ }
+
+ private static class FakeCert extends X509Certificate
+ {
+ private final Principal m_principal;
+
+ public FakeCert(final String principal)
+ {
+ m_principal = new Principal()
+ {
+ public String getName()
+ {
+ return principal;
+ }
+ };
+ }
+
+ public void checkValidity()
+ throws java.security.cert.CertificateExpiredException,
+ java.security.cert.CertificateNotYetValidException
+ {
+
+ }
+
+ public void checkValidity(Date date)
+ throws java.security.cert.CertificateExpiredException,
+ java.security.cert.CertificateNotYetValidException
+ {
+ }
+
+ public int getBasicConstraints()
+ {
+ return 0;
+ }
+
+ public Principal getIssuerDN()
+ {
+ return null;
+ }
+
+ public boolean[] getIssuerUniqueID()
+ {
+ return null;
+ }
+
+ public boolean[] getKeyUsage()
+ {
+ return null;
+ }
+
+ public Date getNotAfter()
+ {
+ return null;
+ }
+
+ public Date getNotBefore()
+ {
+ return null;
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return null;
+ }
+
+ public String getSigAlgName()
+ {
+ return null;
+ }
+
+ public String getSigAlgOID()
+ {
+ return null;
+ }
+
+ public byte[] getSigAlgParams()
+ {
+ return null;
+ }
+
+ public byte[] getSignature()
+ {
+ return null;
+ }
+
+ public Principal getSubjectDN()
+ {
+ return m_principal;
+ }
+
+ public boolean[] getSubjectUniqueID()
+ {
+ return null;
+ }
+
+ public byte[] getTBSCertificate()
+ throws java.security.cert.CertificateEncodingException
+ {
+ return null;
+ }
+
+ public int getVersion()
+ {
+ return 0;
+ }
+
+ public byte[] getEncoded()
+ throws java.security.cert.CertificateEncodingException
+ {
+ return null;
+ }
+
+ public PublicKey getPublicKey()
+ {
+ return null;
+ }
+
+ public String toString()
+ {
+ return m_principal.getName();
+ }
+
+ public void verify(PublicKey key)
+ throws java.security.cert.CertificateException,
+ NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException
+ {
+
+ }
+
+ public void verify(PublicKey key, String sigProvider)
+ throws java.security.cert.CertificateException,
+ NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException
+ {
+
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ return null;
+ }
+
+ public byte[] getExtensionValue(String arg0)
+ {
+ return null;
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ return null;
+ }
+
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ return false;
+ }
+
+ public boolean equals(Object o)
+ {
+ return this == o;
+ }
+
+ public int hashCode()
+ {
+ return System.identityHashCode(this);
+ }
+
+ }
+
+ public AccessControlContext getAccessControlContext(final String[] signers)
{
- final String[] finalSigners =
- (String[]) notNull(signers).toArray(new String[0]);
- return new AccessControlContext(AccessController.getContext(),
- new DomainCombiner()
+ Map certificates = new HashMap();
+ for (int i = 0; i < signers.length; i++)
+ {
+ StringTokenizer tok = new StringTokenizer(signers[i], ";");
+ List certsList = new ArrayList();
+ while (tok.hasMoreTokens())
+ {
+ certsList.add(tok.nextToken());
+ }
+ String[] certs = (String[]) certsList.toArray(new String[certsList
+ .size()]);
+
+ X509Certificate key = new FakeCert(certs[0]);
+ List certList = new ArrayList();
+ certificates.put(key, certList);
+ certList.add(key);
+ for (int j = 1; j < certs.length; j++)
{
- public ProtectionDomain[] combine(ProtectionDomain[] arg0,
- ProtectionDomain[] arg1)
+ certList.add(new FakeCert(certs[j]));
+ }
+ }
+ final Bundle fake = new FakeBundle(certificates);
+ ProtectionDomain domain = new ProtectionDomain(null, null)
+ {
+ public boolean implies(Permission permission)
+ {
+ List posts = new ArrayList();
+ Boolean result = m_pai.hasPermission("", fake, permission,
+ ConditionalPermissionAdminImpl.this, this, null);
+ if (result != null)
+ {
+ return result.booleanValue();
+ }
+ if (eval(posts, new IModule()
{
- return new ProtectionDomain[] { new ProtectionDomain(null,
- null)
+
+ public Bundle getBundle()
{
- public boolean implies(Permission permission)
- {
- return hasPermission(null, null, null, finalSigners,
- this, permission, true, null);
- }
- } };
+ return fake;
+ }
+
+ public ICapability[] getCapabilities()
+ {
+ return null;
+ }
+
+ public Class getClassByDelegation(String arg0)
+ throws ClassNotFoundException
+ {
+ return null;
+ }
+
+ public IContent getContent()
+ {
+ return null;
+ }
+
+ public int getDeclaredActivationPolicy()
+ {
+ return 0;
+ }
+
+ public IRequirement[] getDynamicRequirements()
+ {
+ return null;
+ }
+
+ public URL getEntry(String arg0)
+ {
+ return null;
+ }
+
+ public Map getHeaders()
+ {
+ return null;
+ }
+
+ public String getId()
+ {
+ return null;
+ }
+
+ public InputStream getInputStream(int arg0, String arg1)
+ throws IOException
+ {
+ return null;
+ }
+
+ public R4Library[] getNativeLibraries()
+ {
+ return null;
+ }
+
+ public IRequirement[] getRequirements()
+ {
+ return null;
+ }
+
+ public URL getResourceByDelegation(String arg0)
+ {
+ return null;
+ }
+
+ public Enumeration getResourcesByDelegation(String arg0)
+ {
+ return null;
+ }
+
+ public Object getSecurityContext()
+ {
+ return null;
+ }
+
+ public String getSymbolicName()
+ {
+ return null;
+ }
+
+ public Version getVersion()
+ {
+ return null;
+ }
+
+ public IWire[] getWires()
+ {
+ return null;
+ }
+
+ public boolean hasInputStream(int arg0, String arg1)
+ throws IOException
+ {
+ return false;
+ }
+
+ public boolean isExtension()
+ {
+ return false;
+ }
+
+ public boolean isResolved()
+ {
+ return false;
+ }
+
+ public void setSecurityContext(Object arg0)
+ {
+ }
+ }, permission, m_pai))
+ {
+ if (!posts.isEmpty())
+ {
+ return m_conditions.evalRecursive(posts);
+ }
+ return true;
}
- });
+ return false;
+ }
+ };
+ return new AccessControlContext(new ProtectionDomain[] { domain });
}
public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
@@ -185,7 +797,7 @@
if (result == null)
{
- result = new ConditionalPermissionInfoImpl(this, name);
+ result = new ConditionalPermissionInfoImpl(this, name, true);
result = write(result.getName(), result);
}
@@ -219,14 +831,13 @@
{
synchronized (m_condPermInfos)
{
- result =
- (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
+ result = (ConditionalPermissionInfoImpl) m_condPermInfos
+ .get(name);
if (result == null)
{
- result =
- new ConditionalPermissionInfoImpl(name, conditions,
- permissions, this);
+ result = new ConditionalPermissionInfoImpl(name,
+ conditions, permissions, this, true);
}
else
{
@@ -236,8 +847,8 @@
}
else
{
- result =
- new ConditionalPermissionInfoImpl(conditions, permissions, this);
+ result = new ConditionalPermissionInfoImpl(conditions, permissions,
+ this, true);
}
return write(result.getName(), result);
@@ -284,87 +895,84 @@
/**
* This method does the actual permission check. If it is not a direct check
- * it will try to determine the other bundle domains that will follow
- * automatically in case this is the first check in one permission check.
- * If not then it will keep track of which domains we have already see.
- * While it keeps track it builds up a list of postponed tuples which
- * it will evaluate at the last domain. See the core spec 9.5.1 and following
- * for a general description.
+ * it will try to determine the other bundle domains that will follow
+ * automatically in case this is the first check in one permission check. If
+ * not then it will keep track of which domains we have already see. While
+ * it keeps track it builds up a list of postponed tuples which it will
+ * evaluate at the last domain. See the core spec 9.5.1 and following for a
+ * general description.
*
- * @param felixBundle the bundle in question.
- * @param loader the content loader of the bundle to get access to the jar
- * to check for local permissions.
- * @param root the bundle id.
- * @param signers the signers (this is to support the ACC based on signers)
- * @param pd the bundle protection domain
- * @param permission the permission currently checked
- * @param direct whether this is a direct check or not. direct check will not
- * expect any further bundle domains on the stack
- * @return true in case the permission is granted or there are postponed tuples
- * false if not. Again, see the spec for more explanations.
+ * @param felixBundle
+ * the bundle in question.
+ * @param loader
+ * the content loader of the bundle to get access to the jar to
+ * check for local permissions.
+ * @param root
+ * the bundle id.
+ * @param signers
+ * the signers (this is to support the ACC based on signers)
+ * @param pd
+ * the bundle protection domain
+ * @param permission
+ * the permission currently checked
+ * @param direct
+ * whether this is a direct check or not. direct check will not
+ * expect any further bundle domains on the stack
+ * @return true in case the permission is granted or there are postponed
+ * tuples false if not. Again, see the spec for more explanations.
*/
- public boolean hasPermission(Bundle felixBundle, IContent content, String root,
- String[] signers, ProtectionDomain pd, Permission permission,
- boolean direct, Object admin)
+ public boolean hasPermission(IModule module, IContent content,
+ ProtectionDomain pd, Permission permission, boolean direct, Object admin)
{
// System.out.println(felixBundle + "-" + permission);
List domains = null;
List tuples = null;
Object[] entry = null;
- // first see whether this is the normal case (the special case is for
+ // first see whether this is the normal case (the special case is for
// the ACC based on signers).
- if (signers == null)
+ // In case of a direct call we don't need to look for other pds
+ if (direct)
{
- // In case of a direct call we don't need to look for other pds
- if (direct)
+ domains = new ArrayList();
+ tuples = new ArrayList();
+ domains.add(pd);
+ }
+ else
+ {
+ // Get the other pds from the stck
+ entry = (Object[]) m_stack.get();
+
+ // if there are none then get them from the gripper
+ if (entry == null)
{
- domains = new ArrayList();
- tuples = new ArrayList();
- domains.add(pd);
+ entry = new Object[] { new ArrayList(DomainGripper.grab()),
+ new ArrayList() };
}
else
{
- // Get the other pds from the stck
- entry = (Object[]) m_stack.get();
-
- // if there are none then get them from the gripper
- if (entry == null)
- {
- entry =
- new Object[] { new ArrayList(DomainGripper.grab()),
- new ArrayList() };
- }
- else
- {
- m_stack.set(null);
- }
+ m_stack.set(null);
+ }
- domains = (List) entry[0];
- tuples = (List) entry[1];
- if (!domains.contains(pd))
- {
- // We have been called directly without the direct flag
- domains.clear();
- domains.add(pd);
- }
+ domains = (List) entry[0];
+ tuples = (List) entry[1];
+ if (!domains.contains(pd))
+ {
+ // We have been called directly without the direct flag
+ domains.clear();
+ domains.add(pd);
}
}
// check the local permissions. they need to all the permission if there
// are any
- if (!m_localPermissions.implies(root, content, felixBundle, permission))
+ if (!impliesLocal(module.getBundle(), content, permission))
{
return false;
}
List posts = new ArrayList();
- boolean result = eval(posts, felixBundle, signers, permission, admin);
-
- if (signers != null)
- {
- return result;
- }
+ boolean result = eval(posts, module, permission, admin);
domains.remove(pd);
@@ -378,7 +986,8 @@
if (domains.isEmpty())
{
m_stack.set(null);
- // Now eval the postponed tupels. if the previous eval did return false
+ // Now eval the postponed tupels. if the previous eval did return
+ // false
// tuples will be empty so we don't return from here.
if (!tuples.isEmpty())
{
@@ -387,7 +996,8 @@
}
else
{
- // this is to support recursive permission checks. In case we trigger
+ // this is to support recursive permission checks. In case we
+ // trigger
// a permission check while eval the stack is null until this point
m_stack.set(entry);
}
@@ -395,6 +1005,12 @@
return result;
}
+ public boolean impliesLocal(Bundle felixBundle, IContent content,
+ Permission permission)
+ {
+ return m_localPermissions.implies(content, felixBundle, permission);
+ }
+
public boolean isEmpty()
{
synchronized (m_condPermInfos)
@@ -408,8 +1024,8 @@
// then we make sure their permissions imply the permission and add them
// to the list of posts. Return true in case we pass or have posts
// else falls and clear the posts first.
- private boolean eval(List posts, Bundle bundle, String[] signers,
- Permission permission, Object admin)
+ private boolean eval(List posts, IModule module, Permission permission,
+ Object admin)
{
List condPermInfos = null;
@@ -423,25 +1039,26 @@
}
// Check for implicit permissions like access to file area
- if ((bundle != null)
- && m_permissions.getPermissions(m_permissions.getImplicit(bundle))
- .implies(permission, bundle))
+ if (m_permissions.getPermissions(
+ m_permissions.getImplicit(module.getBundle())).implies(permission,
+ module.getBundle()))
{
return true;
}
-
+ List pls = new ArrayList();
// now do the real thing
for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
{
- ConditionalPermissionInfoImpl cpi =
- (ConditionalPermissionInfoImpl) iter.next();
+ ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
+ .next();
ConditionInfo[] conditions = cpi._getConditionInfos();
List currentPosts = new ArrayList();
- if (!m_conditions.getConditions(bundle, signers, conditions)
- .isSatisfied(currentPosts))
+ Conditions conds = m_conditions.getConditions(module, conditions);
+ if (!conds.isSatisfied(currentPosts, m_permissions
+ .getPermissions(cpi._getPermissionInfos()), permission))
{
continue;
}
@@ -454,13 +1071,127 @@
if (currentPosts.isEmpty())
{
- posts.clear();
+ pls.add(new Object[] { cpi, null });
+ break;
+ }
+ pls.add(new Object[] { cpi, currentPosts, conds });
+ }
+ while (pls.size() > 1)
+ {
+ if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
+ .size() - 1))[0]).isAllow())
+ {
+ pls.remove(pls.size() - 1);
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (pls.size() == 1)
+ {
+ if (((Object[]) pls.get(0))[1] != null)
+ {
+ posts.add(pls.get(0));
+ }
+ return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
+ .isAllow();
+ }
+ for (Iterator iter = pls.iterator(); iter.hasNext();)
+ {
+ posts.add(iter.next());
+ }
+ return !posts.isEmpty();
+ }
+
+ public ConditionalPermissionInfo newConditionalPermissionInfo(
+ String encodedConditionalPermissionInfo)
+ {
+ return new ConditionalPermissionInfoImpl(
+ encodedConditionalPermissionInfo);
+ }
+
+ public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
+ ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
+ {
+ return new ConditionalPermissionInfoImpl(name, conditions, permissions,
+ ConditionalPermissionAdminImpl.this, access
+ .equals(ConditionalPermissionInfo.ALLOW));
+ }
+
+ public ConditionalPermissionUpdate newConditionalPermissionUpdate()
+ {
+ return new ConditionalPermissionUpdate()
+ {
+ List current = null;
+ List out = null;
+ {
+ synchronized (m_condPermInfos)
+ {
+ current = new ArrayList(m_condPermInfos.values());
+ out = new ArrayList(m_condPermInfos.values());
+ }
+ }
+
+ public boolean commit()
+ {
+ synchronized (m_condPermInfos)
+ {
+ if (current.equals(new ArrayList(m_condPermInfos.values())))
+ {
+ m_condPermInfos.clear();
+ write(null, null);
+ for (Iterator iter = out.iterator(); iter.hasNext();)
+ {
+ ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
+ .next();
+ write(cpii.getName(), cpii);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
return true;
}
- posts.add(currentPosts);
+ public List getConditionalPermissionInfos()
+ {
+ return out;
+ }
+ };
+ }
+
+ public boolean handlePAHandle(BundleProtectionDomain pd)
+ {
+ Object[] entry = (Object[]) m_stack.get();
+
+ if (entry == null)
+ {
+ entry = new Object[] { new ArrayList(DomainGripper.grab()),
+ new ArrayList() };
}
- return !posts.isEmpty();
+ ((List) entry[0]).remove(pd);
+ if (((List) entry[0]).isEmpty())
+ {
+ m_stack.set(null);
+ if (!((List) entry[1]).isEmpty())
+ {
+ return m_conditions.evalRecursive(((List) entry[1]));
+ }
+ }
+ else
+ {
+ m_stack.set(entry);
+ }
+
+ return true;
+ }
+
+ public void clearPD()
+ {
+ m_stack.set(null);
}
}
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/ConditionalPermissionInfoImpl.java Sun Jan 10 22:11:27 2010
@@ -30,15 +30,17 @@
/**
* Simple storage class for condperminfos. Additionally, this class can be used
- * to encode and decode infos.
+ * to encode and decode infos.
*/
-public final class ConditionalPermissionInfoImpl implements ConditionalPermissionInfo
+public final class ConditionalPermissionInfoImpl implements
+ ConditionalPermissionInfo
{
private static final Random RANDOM = new Random();
static final ConditionInfo[] CONDITION_INFO = new ConditionInfo[0];
static final PermissionInfo[] PERMISSION_INFO = new PermissionInfo[0];
private final Object m_lock = new Object();
private final String m_name;
+ private final boolean m_allow;
private volatile ConditionalPermissionAdminImpl m_cpai;
private ConditionInfo[] m_conditions;
private PermissionInfo[] m_permissions;
@@ -46,16 +48,18 @@
public ConditionalPermissionInfoImpl(String encoded)
{
StringTokenizer tok = new StringTokenizer(encoded, "\n");
- if (!tok.nextToken().trim().equals("{"))
+ String access = tok.nextToken().trim();
+ if (!(access.equals("ALLOW {") || access.equals("DENY {")))
{
throw new IllegalArgumentException();
}
+ m_allow = access.equals("ALLOW {");
m_cpai = null;
m_name = tok.nextToken().trim().substring(1);
List conditions = new ArrayList();
List permissions = new ArrayList();
- for (String current = tok.nextToken().trim();; current =
- tok.nextToken().trim())
+ for (String current = tok.nextToken().trim();; current = tok
+ .nextToken().trim())
{
if (current.equals("}"))
{
@@ -78,19 +82,18 @@
}
}
- m_conditions =
- conditions.isEmpty() ? CONDITION_INFO
- : (ConditionInfo[]) conditions
- .toArray(new ConditionInfo[conditions.size()]);
- m_permissions =
- permissions.isEmpty() ? PERMISSION_INFO
- : (PermissionInfo[]) permissions
- .toArray(new PermissionInfo[permissions.size()]);
+ m_conditions = conditions.isEmpty() ? CONDITION_INFO
+ : (ConditionInfo[]) conditions.toArray(new ConditionInfo[conditions
+ .size()]);
+ m_permissions = permissions.isEmpty() ? PERMISSION_INFO
+ : (PermissionInfo[]) permissions
+ .toArray(new PermissionInfo[permissions.size()]);
}
public ConditionalPermissionInfoImpl(ConditionalPermissionAdminImpl cpai,
- String name)
+ String name, boolean access)
{
+ m_allow = access;
m_name = name;
m_cpai = cpai;
m_conditions = CONDITION_INFO;
@@ -98,8 +101,10 @@
}
public ConditionalPermissionInfoImpl(ConditionInfo[] conditions,
- PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai)
+ PermissionInfo[] permisions, ConditionalPermissionAdminImpl cpai,
+ boolean access)
{
+ m_allow = access;
m_name = Long.toString(RANDOM.nextLong() ^ System.currentTimeMillis());
m_cpai = cpai;
m_conditions = conditions;
@@ -108,9 +113,11 @@
public ConditionalPermissionInfoImpl(String name,
ConditionInfo[] conditions, PermissionInfo[] permisions,
- ConditionalPermissionAdminImpl cpai)
+ ConditionalPermissionAdminImpl cpai, boolean access)
{
- m_name = name;
+ m_allow = access;
+ m_name = (name != null) ? name : Long.toString(RANDOM.nextLong()
+ ^ System.currentTimeMillis());
m_conditions = conditions;
m_permissions = permisions;
m_cpai = cpai;
@@ -182,6 +189,7 @@
public String getEncoded()
{
StringBuffer buffer = new StringBuffer();
+ buffer.append(m_allow ? "ALLOW " : "DENY ");
buffer.append('{');
buffer.append('\n');
buffer.append('#');
@@ -209,4 +217,15 @@
{
return getEncoded();
}
+
+ public String getAccessDecision()
+ {
+ return m_allow ? ConditionalPermissionInfo.ALLOW
+ : ConditionalPermissionInfo.DENY;
+ }
+
+ public boolean isAllow()
+ {
+ return m_allow;
+ }
}
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/condpermadmin/DomainGripper.java Sun Jan 10 22:11:27 2010
@@ -31,19 +31,19 @@
import org.apache.felix.framework.BundleProtectionDomain;
/**
- * This class is a hack to get all BundleProtectionDomains currently on the
+ * This class is a hack to get all BundleProtectionDomains currently on the
* security stack. This way we don't need to have our own security manager set.
*/
final class DomainGripper implements DomainCombiner, PrivilegedAction
{
- private static final ProtectionDomain[] ALL_PERMISSION_PD =
- new ProtectionDomain[] { new ProtectionDomain(null, null)
+ private static final ProtectionDomain[] ALL_PERMISSION_PD = new ProtectionDomain[] { new ProtectionDomain(
+ null, null)
+ {
+ public boolean implies(Permission perm)
{
- public boolean implies(Permission perm)
- {
- return true;
- }
- } };
+ return true;
+ }
+ } };
// A per thread cache of DomainGripper objects. We might want to wrap them
// in a softreference eventually
@@ -56,8 +56,8 @@
private AccessControlContext m_system = null;
/**
- * Get all bundle protection domains and add them to the m_domains. Then
- * return the ALL_PERMISSION_PD.
+ * Get all bundle protection domains and add them to the m_domains. Then
+ * return the ALL_PERMISSION_PD.
*/
public ProtectionDomain[] combine(ProtectionDomain[] current,
ProtectionDomain[] assigned)
@@ -84,7 +84,7 @@
}
/**
- * Get the current bundle protection domains on the stack up to the last
+ * Get the current bundle protection domains on the stack up to the last
* privileged call.
*/
public static List grab()
@@ -107,8 +107,8 @@
gripper.m_system = AccessController.getContext();
// and merge it with the current combiner (i.e., gripper)
- AccessControlContext context =
- (AccessControlContext) AccessController.doPrivileged(gripper);
+ AccessControlContext context = (AccessControlContext) AccessController
+ .doPrivileged(gripper);
gripper.m_system = null;
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/permissionadmin/PermissionAdminImpl.java Sun Jan 10 22:11:27 2010
@@ -30,22 +30,23 @@
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.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.
+ * 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?
+// 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 static final PermissionInfo[] ALL_PERMISSION = new PermissionInfo[] { new PermissionInfo(
+ AllPermission.class.getName(), "", "") };
+
private final Map m_store = new HashMap();
private final PropertiesCache m_cache;
@@ -59,11 +60,7 @@
{
m_permissions = permissions;
m_cache = cache;
- Map old = m_cache.read(PermissionInfo[].class);
- if (old != null)
- {
- m_store.putAll(old);
- }
+ m_cache.read(PermissionInfo[].class, m_store);
}
public PermissionInfo[] getDefaultPermissions()
@@ -106,71 +103,76 @@
}
/**
- * 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.
+ * 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.
+ * @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)
+ ProtectionDomain pd, IContent content)
{
PermissionInfo[] permissions = null;
- boolean file = false;
+ PermissionInfo[] defaults = null;
+ boolean contains = false;
synchronized (m_store)
{
- if (m_store.containsKey(location))
+ contains = m_store.containsKey(location);
+ permissions = (PermissionInfo[]) m_store.get(location);
+ defaults = m_default;
+ }
+ if (contains)
+ {
+ if (check(permissions, permission, bundle))
{
- permissions = (PermissionInfo[]) m_store.get(location);
- file = true;
+ return Boolean.TRUE;
}
- else if ((cpai == null) || (cpai.isEmpty()))
+ 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 (m_default != null)
+ if (check(defaults, permission, null))
{
- permissions = m_default;
- }
- else
- {
- permissions = ALL_PERMISSION;
+ return Boolean.TRUE;
}
+ return check(m_permissions.getImplicit(bundle), permission,
+ bundle) ? Boolean.TRUE : Boolean.FALSE;
}
- }
- if ((cpai == null) || cpai.isEmpty() || file)
- {
- if (check(permissions, permission, file ? bundle : null))
+ else
{
return Boolean.TRUE;
}
}
-
- permissions = m_permissions.getImplicit(bundle);
-
- if (check(permissions, permission, bundle))
- {
- return Boolean.TRUE;
- }
-
- if ((cpai != null) && !file)
+ else
{
return null;
}
- return Boolean.FALSE;
}
private boolean check(PermissionInfo[] permissions, Permission permission,
Bundle bundle)
{
- Permissions permissionsObject =
- m_permissions.getPermissions(permissions);
+ Permissions permissionsObject = m_permissions
+ .getPermissions(permissions);
return permissionsObject.implies(permission, bundle);
}
Modified: felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java?rev=897721&r1=897720&r2=897721&view=diff
==============================================================================
--- felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java (original)
+++ felix/trunk/framework.security/src/main/java/org/apache/felix/framework/security/util/BundleInputStream.java Sun Jan 10 22:11:27 2010
@@ -33,27 +33,27 @@
import org.apache.felix.moduleloader.IContent;
/**
- * This class makes a given content available as a inputstream with a jar content.
- * In other words the stream can be used as input to a JarInputStream.
+ * This class makes a given content available as a inputstream with a jar
+ * content. In other words the stream can be used as input to a JarInputStream.
*/
public final class BundleInputStream extends InputStream
{
private final IContent m_root;
private final Enumeration m_content;
private final OutputStreamBuffer m_outputBuffer = new OutputStreamBuffer();
-
+
private ByteArrayInputStream m_buffer = null;
private JarOutputStream m_output = null;
-
- public BundleInputStream(IContent root) throws IOException
+
+ public BundleInputStream(IContent root) throws IOException
{
m_root = root;
-
+
List entries = new ArrayList();
-
+
int count = 0;
String manifest = null;
- for (Enumeration e = m_root.getEntries();e.hasMoreElements();)
+ for (Enumeration e = m_root.getEntries(); e.hasMoreElements();)
{
String entry = (String) e.nextElement();
if (entry.equalsIgnoreCase("META-INF/MANIFEST.MF"))
@@ -77,16 +77,16 @@
manifest = "META-INF/MANIFEST.MF";
}
m_content = new IteratorToEnumeration(entries.iterator());
-
+
try
{
m_output = new JarOutputStream(m_outputBuffer);
readNext(manifest);
- m_buffer = new ByteArrayInputStream(
- m_outputBuffer.m_outBuffer.toByteArray());
+ m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+ .toByteArray());
m_outputBuffer.m_outBuffer = null;
- }
+ }
catch (IOException ex)
{
// TODO: figure out what is wrong
@@ -111,24 +111,24 @@
m_buffer = null;
return read();
}
-
+
return result;
}
if (m_content.hasMoreElements())
{
String current = (String) m_content.nextElement();
-
+
readNext(current);
-
+
if (!m_content.hasMoreElements())
{
m_output.close();
m_output = null;
}
- m_buffer = new ByteArrayInputStream(
- m_outputBuffer.m_outBuffer.toByteArray());
+ m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+ .toByteArray());
m_outputBuffer.m_outBuffer = null;
}
@@ -149,7 +149,7 @@
{
throw new IOException("Missing entry");
}
-
+
JarEntry entry = new JarEntry(path);
m_output.putNextEntry(entry);
@@ -169,7 +169,7 @@
{
in.close();
}
- catch (Exception ex)
+ catch (Exception ex)
{
// Not much we can do
}
@@ -180,7 +180,7 @@
m_output.flush();
}
-
+
private static final class OutputStreamBuffer extends OutputStream
{
ByteArrayOutputStream m_outBuffer = null;
@@ -189,12 +189,12 @@
{
m_outBuffer.write(b);
}
-
+
public void write(byte[] buffer) throws IOException
{
m_outBuffer.write(buffer);
- }
-
+ }
+
public void write(byte[] buffer, int offset, int length)
{
m_outBuffer.write(buffer, offset, length);