Updated Branches: refs/heads/master 209aab280 -> 96b36a6b5
[KARAF-2636] Improve security mechanism Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/96b36a6b Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/96b36a6b Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/96b36a6b Branch: refs/heads/master Commit: 96b36a6b5e8a93bb9c0ed908cec4078c9941ff7c Parents: 209aab2 Author: Guillaume Nodet <[email protected]> Authored: Wed Dec 18 16:50:50 2013 +0100 Committer: Guillaume Nodet <[email protected]> Committed: Wed Dec 18 16:50:58 2013 +0100 ---------------------------------------------------------------------- .../src/main/resources/resources/etc/all.policy | 22 +++ .../resources/resources/etc/system.properties | 10 ++ .../standard/src/main/feature/feature.xml | 4 + .../apache/karaf/jaas/modules/JaasHelper.java | 137 +++++++++++++++++++ pom.xml | 6 + .../impl/jline/ConsoleFactoryService.java | 9 +- .../apache/karaf/shell/ssh/ShellCommand.java | 9 +- webconsole/console/pom.xml | 5 + .../webconsole/internal/KarafOsgiManager.java | 12 +- 9 files changed, 210 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/assemblies/features/framework/src/main/resources/resources/etc/all.policy ---------------------------------------------------------------------- diff --git a/assemblies/features/framework/src/main/resources/resources/etc/all.policy b/assemblies/features/framework/src/main/resources/resources/etc/all.policy new file mode 100644 index 0000000..7585f22 --- /dev/null +++ b/assemblies/features/framework/src/main/resources/resources/etc/all.policy @@ -0,0 +1,22 @@ +//=========================================================================== +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//=========================================================================== + +grant { + permission java.security.AllPermission; +}; http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/assemblies/features/framework/src/main/resources/resources/etc/system.properties ---------------------------------------------------------------------- diff --git a/assemblies/features/framework/src/main/resources/resources/etc/system.properties b/assemblies/features/framework/src/main/resources/resources/etc/system.properties index 2ad2002..b1ee30e 100644 --- a/assemblies/features/framework/src/main/resources/resources/etc/system.properties +++ b/assemblies/features/framework/src/main/resources/resources/etc/system.properties @@ -108,3 +108,13 @@ org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.ap # secured by expanding this filter # karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*)) + +# +# Security properties +# +# To enable OSGi security, uncomment the properties below, +# install the framework-security feature and restart. +# +#java.security.policy=${karaf.home}/etc/all.policy +#org.osgi.framework.security=osgi +#org.osgi.framework.trust.repositories=${karaf.home}/etc/trustStore.ks http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/assemblies/features/standard/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml index 9ea23ab..d9e22a7 100644 --- a/assemblies/features/standard/src/main/feature/feature.xml +++ b/assemblies/features/standard/src/main/feature/feature.xml @@ -20,6 +20,10 @@ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> <repository>mvn:org.ops4j.pax.web/pax-web-features/${pax.web.version}/xml/features</repository> + <feature version="${project.version}" description="OSGi Security for Karaf" name="framework-security"> + <bundle start="false" start-level="1">mvn:org.apache.felix/org.apache.felix.framework.security/${felix.framework.security.version}</bundle> + </feature> + <feature name="standard" description="Karaf standard feature" version="${project.version}"> <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.gogo.runtime/${felix.gogo.version}</bundle> <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.console/${project.version}</bundle> http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java ---------------------------------------------------------------------- diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java new file mode 100644 index 0000000..111df95 --- /dev/null +++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/JaasHelper.java @@ -0,0 +1,137 @@ +/* + * 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. + * under the License. + */ +package org.apache.karaf.jaas.modules; + +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.Principal; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import javax.security.auth.Subject; +import javax.security.auth.SubjectDomainCombiner; + +public class JaasHelper { + + public static <T> T doAs(final Subject subject, + final PrivilegedAction<T> action) { + if (action == null) { + throw new NullPointerException(); + } + // set up the new Subject-based AccessControlContext for doPrivileged + final AccessControlContext currentAcc = AccessController.getContext(); + final AccessControlContext newAcc = AccessController.doPrivileged + (new PrivilegedAction<AccessControlContext>() { + public AccessControlContext run() { + if (subject == null) + return new AccessControlContext(currentAcc, null); + else + return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject)); + } + }); + // call doPrivileged and push this new context on the stack + return AccessController.doPrivileged(action, newAcc); + } + + public static <T> T doAs(final Subject subject, + final PrivilegedExceptionAction<T> action) throws PrivilegedActionException { + if (action == null) { + throw new NullPointerException(); + } + // set up the new Subject-based AccessControlContext for doPrivileged + final AccessControlContext currentAcc = AccessController.getContext(); + final AccessControlContext newAcc = AccessController.doPrivileged + (new PrivilegedAction<AccessControlContext>() { + public AccessControlContext run() { + if (subject == null) + return new AccessControlContext(currentAcc, null); + else + return new AccessControlContext(currentAcc, new OsgiSubjectDomainCombiner(subject)); + } + }); + // call doPrivileged and push this new context on the stack + return AccessController.doPrivileged(action, newAcc); + } + + public static class OsgiSubjectDomainCombiner extends SubjectDomainCombiner { + + private final Subject subject; + + public OsgiSubjectDomainCombiner(Subject subject) { + super(subject); + this.subject = subject; + } + + public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, + ProtectionDomain[] assignedDomains) { + int cLen = (currentDomains == null ? 0 : currentDomains.length); + int aLen = (assignedDomains == null ? 0 : assignedDomains.length); + ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen]; + Principal[] principals = subject.getPrincipals().toArray(new Principal[0]); + for (int i = 0; i < cLen; i++) { + newDomains[i] = new DelegatingProtectionDomain(currentDomains[i], principals); + } + for (int i = 0; i < aLen; i++) { + newDomains[cLen + i] = assignedDomains[i]; + } + newDomains = optimize(newDomains); + return newDomains; + } + + private ProtectionDomain[] optimize(ProtectionDomain[] domains) { + if (domains == null || domains.length == 0) { + return null; + } + ProtectionDomain[] optimized = new ProtectionDomain[domains.length]; + ProtectionDomain pd; + int num = 0; + for (int i = 0; i < domains.length; i++) { + if ((pd = domains[i]) != null) { + boolean found = false; + for (int j = 0; j < num && !found; j++) { + found = (optimized[j] == pd); + } + if (!found) { + optimized[num++] = pd; + } + } + } + if (num > 0 && num < domains.length) { + ProtectionDomain[] downSize = new ProtectionDomain[num]; + System.arraycopy(optimized, 0, downSize, 0, downSize.length); + optimized = downSize; + } + return ((num == 0 || optimized.length == 0) ? null : optimized); + } + } + + public static class DelegatingProtectionDomain extends ProtectionDomain { + + private final ProtectionDomain delegate; + + DelegatingProtectionDomain(ProtectionDomain delegate, Principal[] principals) { + super(delegate.getCodeSource(), delegate.getPermissions(), delegate.getClassLoader(), principals); + this.delegate = delegate; + } + + @Override + public boolean implies(Permission permission) { + return delegate.implies(permission); + } + + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 298500a..8c5c82c 100644 --- a/pom.xml +++ b/pom.xml @@ -152,6 +152,7 @@ <felix.configadmin.version>1.6.0</felix.configadmin.version> <felix.fileinstall.version>3.2.6</felix.fileinstall.version> <felix.framework.version>4.2.1</felix.framework.version> + <felix.framework.security.version>2.2.0</felix.framework.security.version> <felix.gogo.version>0.10.0</felix.gogo.version> <felix.plugin.version>2.4.0</felix.plugin.version> <felix.utils.version>1.4.0</felix.utils.version> @@ -819,6 +820,11 @@ </dependency> <dependency> <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.framework.security</artifactId> + <version>${felix.framework.security.version}</version> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> <artifactId>org.osgi.service.obr</artifactId> <version>${felix.obr.version}</version> </dependency> http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java index cdd9453..4c2c90b 100644 --- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java +++ b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java @@ -34,12 +34,19 @@ import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Function; import org.apache.felix.service.threadio.ThreadIO; import org.apache.karaf.jaas.boot.principal.UserPrincipal; +import org.apache.karaf.jaas.modules.JaasHelper; import org.apache.karaf.shell.console.Console; import org.apache.karaf.shell.console.ConsoleFactory; import org.osgi.framework.BundleContext; public class ConsoleFactoryService implements ConsoleFactory { + private static final Class[] SECURITY_BUGFIX = { + JaasHelper.class, + JaasHelper.OsgiSubjectDomainCombiner.class, + JaasHelper.DelegatingProtectionDomain.class, + }; + private final BundleContext bundleContext; public ConsoleFactoryService(BundleContext bc) { @@ -97,7 +104,7 @@ public class ConsoleFactoryService implements ConsoleFactory { if (subject != null) { CommandSession session = console.getSession(); session.put("USER", userName); - Subject.doAs(subject, new PrivilegedAction<Object>() { + JaasHelper.doAs(subject, new PrivilegedAction<Object>() { public Object run() { doRun(); return null; http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java ---------------------------------------------------------------------- diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java index 9b68691..a825f07 100644 --- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java +++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommand.java @@ -28,6 +28,7 @@ import javax.security.auth.Subject; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Converter; +import org.apache.karaf.jaas.modules.JaasHelper; import org.apache.karaf.shell.util.ShellUtil; import org.apache.karaf.util.StreamUtils; import org.apache.sshd.server.Command; @@ -44,6 +45,12 @@ public class ShellCommand implements Command, SessionAware { private static final Logger LOGGER = LoggerFactory.getLogger(ShellCommand.class); + private static final Class[] SECURITY_BUGFIX = { + JaasHelper.class, + JaasHelper.OsgiSubjectDomainCombiner.class, + JaasHelper.DelegatingProtectionDomain.class, + }; + private String command; private InputStream in; private OutputStream out; @@ -92,7 +99,7 @@ public class ShellCommand implements Command, SessionAware { try { String scriptFileName = System.getProperty(SHELL_INIT_SCRIPT); executeScript(scriptFileName, session); - result = Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { + result = JaasHelper.doAs(subject, new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { return session.execute(command); } http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/webconsole/console/pom.xml ---------------------------------------------------------------------- diff --git a/webconsole/console/pom.xml b/webconsole/console/pom.xml index 08b1560..edf10d9 100644 --- a/webconsole/console/pom.xml +++ b/webconsole/console/pom.xml @@ -57,6 +57,11 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.karaf.jaas</groupId> + <artifactId>org.apache.karaf.jaas.modules</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <scope>provided</scope> http://git-wip-us.apache.org/repos/asf/karaf/blob/96b36a6b/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java ---------------------------------------------------------------------- diff --git a/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java b/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java index c7aef84..2275c41 100644 --- a/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java +++ b/webconsole/console/src/main/java/org/apache/felix/webconsole/internal/KarafOsgiManager.java @@ -27,11 +27,19 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.felix.webconsole.internal.servlet.OsgiManager; +import org.apache.karaf.jaas.modules.JaasHelper; import org.osgi.framework.BundleContext; public class KarafOsgiManager extends OsgiManager { private static final long serialVersionUID = 1090035807469459598L; - public static final String SUBJECT_RUN_AS = "karaf.subject.runas"; + + private static final Class[] SECURITY_BUGFIX = { + JaasHelper.class, + JaasHelper.OsgiSubjectDomainCombiner.class, + JaasHelper.DelegatingProtectionDomain.class, + }; + + public static final String SUBJECT_RUN_AS = "karaf.subject.runas"; public KarafOsgiManager(BundleContext bundleContext) { super(bundleContext); @@ -42,7 +50,7 @@ public class KarafOsgiManager extends OsgiManager { Object obj = req.getAttribute(SUBJECT_RUN_AS); if (obj instanceof Subject) { try { - Subject.doAs((Subject) obj, new PrivilegedExceptionAction<Object>() { + JaasHelper.doAs((Subject) obj, new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { doService(req, res); return null;
