From da9110a97b207350b1f09eb9d6ed7e42209a5e60 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 2 Sep 2008 21:52:05 +0000 Subject: Bug 242799 [osgi R4.2] implement changes to conditional permission admin RFC 120 --- .../securityadmin/SecurityAdminUnitTests.java | 121 +++++++++++++++++++++ .../osgi/internal/permadmin/SecurityAdmin.java | 94 ++++++++++++++-- .../internal/permadmin/SecurityAdminUtils.java | 71 ------------ .../osgi/internal/permadmin/SecurityRow.java | 3 +- 4 files changed, 209 insertions(+), 80 deletions(-) delete mode 100644 bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdminUtils.java diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java index cbbfe0007..a1ee40b33 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/securityadmin/SecurityAdminUnitTests.java @@ -43,6 +43,10 @@ public class SecurityAdminUnitTests extends AbstractBundleTests { private static final ConditionInfo POST_MUT_SAT = new ConditionInfo("ext.framework.b.TestCondition", new String[] {"POST_MUT_SAT", "true", "true", "true"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ private static final ConditionInfo POST_MUT_UNSAT = new ConditionInfo("ext.framework.b.TestCondition", new String[] {"POST_MUT_UNSAT", "true", "true", "false"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + private static final ConditionInfo SIGNER_CONDITION1 = new ConditionInfo("org.osgi.service.condpermadmin.BundleSignerCondition", new String[] {"*;cn=test1,c=US"}); //$NON-NLS-1$//$NON-NLS-2$ + private static final ConditionInfo SIGNER_CONDITION2 = new ConditionInfo("org.osgi.service.condpermadmin.BundleSignerCondition", new String[] {"*;cn=test2,c=US"}); //$NON-NLS-1$//$NON-NLS-2$ + private static final ConditionInfo NOT_SIGNER_CONDITION1 = new ConditionInfo("org.osgi.service.condpermadmin.BundleSignerCondition", new String[] {"*;cn=test1,c=US", "!"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + //private static final ConditionInfo POST_MUT_NOTSAT = new ConditionInfo("ext.framework.b.TestCondition", new String[] {"POST_MUT_NOTSAT", "true", "true", "false"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //private static final ConditionInfo POST_NOTMUT_SAT = new ConditionInfo("ext.framework.b.TestCondition", new String[] {"POST_NOTMUT_SAT", "true", "false", "true"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //private static final ConditionInfo POST_NOTMUT_NOTSAT = new ConditionInfo("ext.framework.b.TestCondition", new String[] {"POST_NOTMUT_NOTSAT", "true", "false", "false"}); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ @@ -595,6 +599,123 @@ public class SecurityAdminUnitTests extends AbstractBundleTests { testSMPermission(sm, pds, new FilePermission("test", "read"), true); //$NON-NLS-1$ //$NON-NLS-2$ } + public void testAccessControlContext01() { + SecurityAdmin securityAdmin = createSecurityAdmin(null); + ConditionalPermissionsUpdate update = securityAdmin.createConditionalPermissionsUpdate(); + List rows = update.getConditionalPermissionInfoBases(); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION1}, READONLY_INFOS, ConditionalPermissionInfoBase.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + + AccessControlContext acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test1,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (AccessControlException e) { + fail("Unexpected AccessControlExcetpion", e); //$NON-NLS-1$ + } + } + + public void testAccessControlContext02() { + SecurityAdmin securityAdmin = createSecurityAdmin(null); + ConditionalPermissionsUpdate update = securityAdmin.createConditionalPermissionsUpdate(); + List rows = update.getConditionalPermissionInfoBases(); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION1}, READONLY_INFOS, ConditionalPermissionInfoBase.ALLOW)); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION1}, READWRITE_INFOS, ConditionalPermissionInfoBase.DENY)); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION1}, READWRITE_INFOS, ConditionalPermissionInfoBase.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + + AccessControlContext acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test1,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (AccessControlException e) { + fail("Unexpected AccessControlExcetpion", e); //$NON-NLS-1$ + } + } + + public void testAccessControlContext03() { + SecurityAdmin securityAdmin = createSecurityAdmin(null); + ConditionalPermissionsUpdate update = securityAdmin.createConditionalPermissionsUpdate(); + List rows = update.getConditionalPermissionInfoBases(); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION1}, READONLY_INFOS, ConditionalPermissionInfoBase.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + + AccessControlContext acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test2,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + + update = securityAdmin.createConditionalPermissionsUpdate(); + rows = update.getConditionalPermissionInfoBases(); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {SIGNER_CONDITION2}, READONLY_INFOS, ConditionalPermissionInfoBase.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test2,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (AccessControlException e) { + fail("Unexpected AccessControlExcetpion", e); //$NON-NLS-1$ + } + } + + public void testAccessControlContext04() { + SecurityAdmin securityAdmin = createSecurityAdmin(null); + ConditionalPermissionsUpdate update = securityAdmin.createConditionalPermissionsUpdate(); + List rows = update.getConditionalPermissionInfoBases(); + rows.add(securityAdmin.createConditionalPermissionInfoBase(null, new ConditionInfo[] {NOT_SIGNER_CONDITION1}, READONLY_INFOS, ConditionalPermissionInfoBase.ALLOW)); + assertTrue("failed to commit", update.commit()); //$NON-NLS-1$ + AccessControlContext acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test1,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + + acc = securityAdmin.getAccessControlContext(new String[] {"cn=t1,cn=FR;cn=test2,c=US"}); //$NON-NLS-1$ + try { + acc.checkPermission(new FilePermission("test", "write")); //$NON-NLS-1$ //$NON-NLS-2$ + fail("expecting AccessControlExcetpion"); //$NON-NLS-1$ + } catch (AccessControlException e) { + // expected + } + try { + acc.checkPermission(new FilePermission("test", "read")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (AccessControlException e) { + fail("Unexpected AccessControlExcetpion", e); //$NON-NLS-1$ + } + } + private void testSMPermission(EquinoxSecurityManager sm, ProtectionDomain[] pds, Permission permission, boolean expectedToPass) { AccessControlContext acc = new AccessControlContext(pds); try { diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java index 601f2752d..e154d8b83 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdmin.java @@ -10,13 +10,15 @@ *******************************************************************************/ package org.eclipse.osgi.internal.permadmin; -import java.io.File; -import java.io.IOException; +import java.io.*; +import java.net.URL; import java.security.*; import java.util.*; import org.eclipse.osgi.framework.adaptor.PermissionStorage; import org.eclipse.osgi.framework.internal.core.*; +import org.eclipse.osgi.internal.signedcontent.DNChainMatching; import org.osgi.framework.AdminPermission; +import org.osgi.framework.FrameworkEvent; import org.osgi.service.condpermadmin.*; import org.osgi.service.permissionadmin.PermissionAdmin; import org.osgi.service.permissionadmin.PermissionInfo; @@ -31,7 +33,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi } private static final String ADMIN_IMPLIED_ACTIONS = AdminPermission.RESOURCE + ',' + AdminPermission.METADATA + ',' + AdminPermission.CLASS; - + private static final PermissionInfo[] EMPTY_PERM_INFO = new PermissionInfo[0]; /* @GuardedBy(lock) */ private final PermissionAdminTable permAdminTable = new PermissionAdminTable(); /* @GuardedBy(lock) */ @@ -53,7 +55,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi this.supportedSecurityManager = supportedSecurityManager; this.framework = framework; this.permissionStorage = new SecurePermissionStorage(permissionStorage); - this.impliedPermissionInfos = SecurityAdminUtils.getPermissionInfos(getClass().getResource(Constants.OSGI_BASE_IMPLIED_PERMISSIONS), framework); + this.impliedPermissionInfos = SecurityAdmin.getPermissionInfos(getClass().getResource(Constants.OSGI_BASE_IMPLIED_PERMISSIONS), framework); String[] encodedDefaultInfos = permissionStorage.getPermissionData(null); PermissionInfo[] defaultInfos = getPermissionInfos(encodedDefaultInfos); if (defaultInfos != null) @@ -215,8 +217,39 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi } public AccessControlContext getAccessControlContext(String[] signers) { - // TODO Auto-generated method stub - return null; + Enumeration infos = getConditionalPermissionInfos(); + ArrayList permissionInfos = new ArrayList(); + if (infos != null) { + while (infos.hasMoreElements()) { + SecurityRow condPermInfo = (SecurityRow) infos.nextElement(); + if (!ConditionalPermissionInfoBase.ALLOW.equals(condPermInfo.getGrantDecision())) + break; // TODO need to clarify the spec WRT DENY rows + ConditionInfo[] condInfo = condPermInfo.getConditionInfos(); + boolean match = true; + for (int i = 0; match && i < condInfo.length; i++) { + if (BundleSignerCondition.class.getName().equals(condInfo[i].getType())) { + String[] args = condInfo[i].getArgs(); + String condSigners = args.length > 0 ? args[0] : null; + if (condSigners != null) { + boolean negate = (args.length == 2) ? "!".equals(args[1]) : false; //$NON-NLS-1$ + for (int j = 0; j < signers.length && match; j++) + match = (negate ^ DNChainMatching.match(signers[i], condSigners)); + } else { + match = false; + } + } else { + match = false; + } + } + if (match) { + PermissionInfo[] addPermInfos = condPermInfo.getPermissionInfos(); + for (int i = 0; i < addPermInfos.length; i++) + permissionInfos.add(addPermInfos[i]); + } + } + } + PermissionInfoCollection collection = new PermissionInfoCollection((PermissionInfo[]) permissionInfos.toArray(new PermissionInfo[permissionInfos.size()])); + return new AccessControlContext(collection == null ? new ProtectionDomain[0] : new ProtectionDomain[] {new ProtectionDomain(null, collection)}); } public ConditionalPermissionInfo getConditionalPermissionInfo(String name) { @@ -309,7 +342,7 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi public EquinoxProtectionDomain createProtectionDomain(AbstractBundle bundle) { PermissionInfoCollection impliedPermissions = getImpliedPermission(bundle); - PermissionInfo[] restrictedInfos = getFileRelativeInfos(SecurityAdminUtils.getPermissionInfos(bundle.getEntry("OSGI-INF/permissions.perm"), framework), bundle); //$NON-NLS-1$ + PermissionInfo[] restrictedInfos = getFileRelativeInfos(SecurityAdmin.getPermissionInfos(bundle.getEntry("OSGI-INF/permissions.perm"), framework), bundle); //$NON-NLS-1$ PermissionInfoCollection restrictedPermissions = restrictedInfos == null ? null : new PermissionInfoCollection(restrictedInfos); BundlePermissions bundlePermissions = new BundlePermissions(bundle, this, impliedPermissions, restrictedPermissions); return new EquinoxProtectionDomain(bundlePermissions); @@ -369,4 +402,51 @@ public final class SecurityAdmin implements PermissionAdmin, ConditionalPermissi return null; } } + + private static PermissionInfo[] getPermissionInfos(URL resource, Framework framework) { + if (resource == null) + return null; + PermissionInfo[] info = EMPTY_PERM_INFO; + DataInputStream in = null; + try { + in = new DataInputStream(resource.openStream()); + ArrayList permissions = new ArrayList(); + BufferedReader reader; + try { + reader = new BufferedReader(new InputStreamReader(in, "UTF8")); //$NON-NLS-1$ + } catch (UnsupportedEncodingException e) { + reader = new BufferedReader(new InputStreamReader(in)); + } + + while (true) { + String line = reader.readLine(); + if (line == null) /* EOF */ + break; + line = line.trim(); + if ((line.length() == 0) || line.startsWith("#") || line.startsWith("//")) /* comments *///$NON-NLS-1$ //$NON-NLS-2$ + continue; + + try { + permissions.add(new PermissionInfo(line)); + } catch (IllegalArgumentException iae) { + /* incorrectly encoded permission */ + if (framework != null) + framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.getBundle(0), iae); + } + } + int size = permissions.size(); + if (size > 0) + info = (PermissionInfo[]) permissions.toArray(new PermissionInfo[size]); + } catch (IOException e) { + // do nothing + } finally { + try { + if (in != null) + in.close(); + } catch (IOException ee) { + // do nothing + } + } + return info; + } } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdminUtils.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdminUtils.java deleted file mode 100644 index 1f4a9e664..000000000 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityAdminUtils.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.osgi.internal.permadmin; - -import java.io.*; -import java.net.URL; -import java.util.ArrayList; -import org.eclipse.osgi.framework.internal.core.Framework; -import org.osgi.framework.FrameworkEvent; -import org.osgi.service.condpermadmin.ConditionInfo; -import org.osgi.service.permissionadmin.PermissionInfo; - -public class SecurityAdminUtils { - public static final ConditionInfo[] EMPTY_COND_INFO = new ConditionInfo[0]; - public static final PermissionInfo[] EMPTY_PERM_INFO = new PermissionInfo[0]; - - static PermissionInfo[] getPermissionInfos(URL resource, Framework framework) { - if (resource == null) - return null; - PermissionInfo[] info = EMPTY_PERM_INFO; - DataInputStream in = null; - try { - in = new DataInputStream(resource.openStream()); - ArrayList permissions = new ArrayList(); - BufferedReader reader; - try { - reader = new BufferedReader(new InputStreamReader(in, "UTF8")); //$NON-NLS-1$ - } catch (UnsupportedEncodingException e) { - reader = new BufferedReader(new InputStreamReader(in)); - } - - while (true) { - String line = reader.readLine(); - if (line == null) /* EOF */ - break; - line = line.trim(); - if ((line.length() == 0) || line.startsWith("#") || line.startsWith("//")) /* comments *///$NON-NLS-1$ //$NON-NLS-2$ - continue; - - try { - permissions.add(new PermissionInfo(line)); - } catch (IllegalArgumentException iae) { - /* incorrectly encoded permission */ - if (framework != null) - framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.getBundle(0), iae); - } - } - int size = permissions.size(); - if (size > 0) - info = (PermissionInfo[]) permissions.toArray(new PermissionInfo[size]); - } catch (IOException e) { - // do nothing - } finally { - try { - if (in != null) - in.close(); - } catch (IOException ee) { - // do nothing - } - } - return info; - } -} diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java index 409767d24..adf43b1e1 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/permadmin/SecurityRow.java @@ -180,8 +180,7 @@ public final class SecurityRow implements ConditionalPermissionInfo { Condition condition = conditions[i]; if (condition == null) continue; // this condition must have been satisfied && !mutable in a previous check - // TODO need to clarify on the spec if nonMutable postponed conditions can be evaluated immediately - if (!isPostponed(condition) || !condition.isMutable()) { + if (!isPostponed(condition)) { if (condition.isSatisfied()) { if (!condition.isMutable()) conditions[i] = null; // ignore this condition for future checks -- cgit v1.2.3