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 2008/03/07 01:37:47 UTC

svn commit: r634480 [3/3] - in /felix/trunk/framework/security: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/framework/ src/main/java/org/apache/felix/frame...

Added: felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java?rev=634480&view=auto
==============================================================================
--- felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java (added)
+++ felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleLocationCondition.java Thu Mar  6 16:37:30 2008
@@ -0,0 +1,133 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleLocationCondition.java,v 1.18 2006/06/16 16:31:37 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.service.condpermadmin;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Hashtable;
+
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.*;
+
+/**
+ * Condition to test if the location of a bundle matches a pattern. Pattern
+ * matching is done according to the filter string matching rules.
+ * 
+ * @version $Revision: 1.18 $
+ */
+public class BundleLocationCondition
+{
+    private static final String CONDITION_TYPE =
+        "org.osgi.service.condpermadmin.BundleLocationCondition";
+
+    /**
+     * Constructs a condition that tries to match the passed Bundle's location
+     * to the location pattern.
+     * 
+     * @param bundle
+     *                The Bundle being evaluated.
+     * @param info
+     *                The ConditionInfo to construct the condition for. The args
+     *                of the ConditionInfo must be a single String which
+     *                specifies the location pattern to match against the Bundle
+     *                location. Matching is done according to the filter string
+     *                matching rules. Any '*' characters in the location
+     *                argument are used as wildcards when matching bundle
+     *                locations unless they are escaped with a '\' character.
+     * @return Condition object for the requested condition.
+     */
+    static public Condition getCondition(final Bundle bundle, ConditionInfo info)
+    {
+        if (!CONDITION_TYPE.equals(info.getType()))
+            throw new IllegalArgumentException(
+                "ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
+        String[] args = info.getArgs();
+        if (args.length != 1)
+            throw new IllegalArgumentException("Illegal number of args: "
+                + args.length);
+        String bundleLocation =
+            (String) AccessController.doPrivileged(new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    return bundle.getLocation();
+                }
+            });
+        Filter filter = null;
+        try
+        {
+            filter =
+                new FilterImpl("(location=" + escapeLocation(args[0]) + ")");
+        }
+        catch (InvalidSyntaxException e)
+        {
+            // this should never happen, but just incase
+            throw new RuntimeException("Invalid filter: " + e.getFilter());
+        }
+        Hashtable matchProps = new Hashtable(2);
+        matchProps.put("location", bundleLocation);
+        return filter.match(matchProps) ? Condition.TRUE : Condition.FALSE;
+    }
+
+    private BundleLocationCondition()
+    {
+        // private constructor to prevent objects of this type
+    }
+
+    /**
+     * Escape the value string such that '(', ')' and '\' are escaped. The '\'
+     * char is only escaped if it is not followed by a '*'.
+     * 
+     * @param value
+     *                unescaped value string.
+     * @return escaped value string.
+     */
+    private static String escapeLocation(String value)
+    {
+        boolean escaped = false;
+        int inlen = value.length();
+        int outlen = inlen << 1; /* inlen * 2 */
+
+        char[] output = new char[outlen];
+        value.getChars(0, inlen, output, inlen);
+
+        int cursor = 0;
+        for (int i = inlen; i < outlen; i++)
+        {
+            char c = output[i];
+            switch (c)
+            {
+                case '\\':
+                    if (i + 1 < outlen && output[i + 1] == '*')
+                        break;
+                case '(':
+                case ')':
+                    output[cursor] = '\\';
+                    cursor++;
+                    escaped = true;
+                    break;
+            }
+
+            output[cursor] = c;
+            cursor++;
+        }
+
+        return escaped ? new String(output, 0, cursor) : value;
+    }
+}

Added: felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java?rev=634480&view=auto
==============================================================================
--- felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java (added)
+++ felix/trunk/framework/security/src/main/java/org/osgi/service/condpermadmin/BundleSignerCondition.java Thu Mar  6 16:37:30 2008
@@ -0,0 +1,229 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleSignerCondition.java,v 1.10 2006/06/16 16:31:37 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.service.condpermadmin;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * Condition to test if the signer of a bundle matches a pattern. Since the
+ * bundle's signer can only change when the bundle is updated, this condition is
+ * immutable.
+ * <p>
+ * The condition expressed using a single String that specifies a Distinguished
+ * Name (DN) chain to match bundle signers against. DN's are encoded using IETF
+ * RFC 2253. Usually signers use certificates that are issued by certificate
+ * authorities, which also have a corresponding DN and certificate. The
+ * certificate authorities can form a chain of trust where the last DN and
+ * certificate is known by the framework. The signer of a bundle is expressed as
+ * signers DN followed by the DN of its issuer followed by the DN of the next
+ * issuer until the DN of the root certificate authority. Each DN is separated
+ * by a semicolon.
+ * <p>
+ * A bundle can satisfy this condition if one of its signers has a DN chain that
+ * matches the DN chain used to construct this condition. Wildcards (`*') can be
+ * used to allow greater flexibility in specifying the DN chains. Wildcards can
+ * be used in place of DNs, RDNs, or the value in an RDN. If a wildcard is used
+ * for a value of an RDN, the value must be exactly "*" and will match any value
+ * for the corresponding type in that RDN. If a wildcard is used for a RDN, it
+ * must be the first RDN and will match any number of RDNs (including zero
+ * RDNs).
+ * 
+ * @version $Revision: 1.10 $
+ */
+/*
+ * TODO: In our case the above is not correct. We don't make this an immutable
+ * condition because the spec is somewhat ambiguous in regard to when the
+ * signature change. This probably has to be clarified and then revisited later.
+ */
+public class BundleSignerCondition
+{
+    /*
+     * NOTE: A framework implementor may also choose to replace this class in
+     * their distribution with a class that directly interfaces with the
+     * framework implementation. This replacement class MUST NOT alter the
+     * public/protected signature of this class.
+     */
+
+    private static final String CONDITION_TYPE =
+        "org.osgi.service.condpermadmin.BundleSignerCondition";
+
+    /**
+     * Constructs a Condition that tries to match the passed Bundle's location
+     * to the location pattern.
+     * 
+     * @param bundle
+     *                The Bundle being evaluated.
+     * @param info
+     *                The ConditionInfo to construct the condition for. The args
+     *                of the ConditionInfo specify a single String specifying
+     *                the chain of distinguished names pattern to match against
+     *                the signer of the Bundle.
+     * @return A Condition which checks the signers of the specified bundle.
+     */
+    static public Condition getCondition(Bundle bundle, ConditionInfo info)
+    {
+        if (!CONDITION_TYPE.equals(info.getType()))
+            throw new IllegalArgumentException(
+                "ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
+        final String[] args = info.getArgs();
+        if (args.length != 1)
+            throw new IllegalArgumentException("Illegal number of args: "
+                + args.length);
+
+        return new ConditionImpl(bundle, "(signer=" + escapeFilter(args[0])
+            + ")");
+
+    }
+
+    private static String escapeFilter(String string)
+    {
+        boolean escaped = false;
+        int inlen = string.length();
+        int outlen = inlen << 1; /* inlen * 2 */
+
+        char[] output = new char[outlen];
+        string.getChars(0, inlen, output, inlen);
+
+        int cursor = 0;
+        for (int i = inlen; i < outlen; i++)
+        {
+            char c = output[i];
+            switch (c)
+            {
+                case '\\':
+                case '(':
+                case ')':
+                case '*':
+                    output[cursor] = '\\';
+                    cursor++;
+                    escaped = true;
+                    break;
+            }
+
+            output[cursor] = c;
+            cursor++;
+        }
+
+        return escaped ? new String(output, 0, cursor) : string;
+    }
+
+    private BundleSignerCondition()
+    {
+        // private constructor to prevent objects of this type
+    }
+}
+
+final class ConditionImpl implements Condition, PrivilegedExceptionAction
+{
+    private static final Method m_getSignerMatcher;
+
+    static
+    {
+        m_getSignerMatcher =
+            (Method) AccessController.doPrivileged(new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    Method getSignerMatcher = null;
+                    try
+                    {
+                        getSignerMatcher =
+                            Class.forName(
+                                "org.apache.felix.framework.BundleImpl")
+                                .getDeclaredMethod("getSignerMatcher", null);
+                        getSignerMatcher.setAccessible(true);
+                    }
+                    catch (Exception ex)
+                    {
+                        ex.printStackTrace();
+                        getSignerMatcher = null;
+                    }
+                    return getSignerMatcher;
+                }
+            });
+    }
+
+    private final Bundle m_bundle;
+    private final Filter m_filter;
+    private final Dictionary m_dict;
+
+    ConditionImpl(Bundle bundle, String filter)
+    {
+        m_bundle = bundle;
+        try
+        {
+            m_filter = new FilterImpl(filter);
+        }
+        catch (InvalidSyntaxException e)
+        {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+        try
+        {
+            Object signerMatcher = AccessController.doPrivileged(this);
+            m_dict = new Hashtable();
+            m_dict.put("signer", signerMatcher);
+        }
+        catch (PrivilegedActionException e)
+        {
+            if (e.getException() instanceof RuntimeException)
+            {
+                throw (RuntimeException) e.getException();
+            }
+
+            throw new RuntimeException(e.getException().getMessage());
+        }
+    }
+
+    public boolean isMutable()
+    {
+        return true;
+    }
+
+    public boolean isPostponed()
+    {
+        return false;
+    }
+
+    public Object run() throws Exception
+    {
+        return m_getSignerMatcher.invoke(m_bundle, null);
+    }
+
+    public boolean isSatisfied()
+    {
+        return m_filter.match(m_dict);
+    }
+
+    public boolean isSatisfied(Condition[] conditions, Dictionary context)
+    {
+        return false;
+    }
+}
\ No newline at end of file