This is an automated email from the ASF dual-hosted git repository.
ffang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/master by this push:
new f8849fc [KARAF-5506]ensure we also check the ACL for alias cmds
before auto-completer-more change
f8849fc is described below
commit f8849fc8d247c5a8ffbbedf98f5daf7b7ddf3ef7
Author: Freeman Fang <[email protected]>
AuthorDate: Wed Nov 29 10:47:33 2017 +0800
[KARAF-5506]ensure we also check the ACL for alias cmds before
auto-completer-more change
---
.../shell/impl/console/CommandsCompleter.java | 2 +-
.../shell/impl/console/ConsoleSessionImpl.java | 2 +-
.../karaf/shell/impl/console/RegistryImpl.java | 7 ++
.../shell/impl/console/SessionFactoryImpl.java | 3 +
.../impl/console/osgi/secured/AliasCommand.java | 48 +++++++++
.../osgi/secured/SecuredSessionFactoryImpl.java | 110 ++++++++++++++++++++-
6 files changed, 165 insertions(+), 7 deletions(-)
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
index 99833b7..165ed2b 100644
---
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
@@ -286,7 +286,7 @@ public class CommandsCompleter extends
org.apache.karaf.shell.support.completers
get(originalCmd.substring(0, index));
}
if (securityCmd instanceof SecuredCommand) {
- if
(((SecuredSessionFactoryImpl)factory).isVisible(scope, command)
+ if
(((SecuredSessionFactoryImpl)factory).isAliasVisible(scope, command)
&&
((SecuredSessionFactoryImpl)factory).isVisible(((SecuredCommand)securityCmd).getScope(),
((SecuredCommand)securityCmd).getName())) {
aliases.add(var);
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
index 713b3ca..b0e2765 100644
---
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
@@ -195,7 +195,7 @@ public class ConsoleSessionImpl implements Session {
history = new HistoryWrapper(reader.getHistory());
// Registry
- registry = new RegistryImpl(factory.getRegistry());
+ registry = new RegistryImpl(factory.getRegistry(), this);
registry.register(factory);
registry.register(this);
registry.register(registry);
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/RegistryImpl.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/RegistryImpl.java
index 06e2456..106f349 100644
---
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/RegistryImpl.java
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/RegistryImpl.java
@@ -27,17 +27,24 @@ import java.util.concurrent.Callable;
import org.apache.karaf.shell.api.console.Command;
import org.apache.karaf.shell.api.console.Registry;
+import org.apache.karaf.shell.api.console.Session;
public class RegistryImpl implements Registry {
protected final Registry parent;
protected final Map<Object, Object> services = new LinkedHashMap<>();
+ protected Session session;
private final Map<String, List<Command>> commands = new HashMap<>();
public RegistryImpl(Registry parent) {
this.parent = parent;
}
+ public RegistryImpl(Registry parent, Session session) {
+ this.parent = parent;
+ this.session = session;
+ }
+
@Override
public List<Command> getCommands() {
return getServices(Command.class);
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
index 13e27ac..8f69d2a 100644
---
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
@@ -157,6 +157,9 @@ public class SessionFactoryImpl extends RegistryImpl
implements SessionFactory,
throw new IllegalStateException("SessionFactory has been
closed");
}
final Session session = new ConsoleSessionImpl(this,
commandProcessor, threadIO, in, out, err, term, encoding, closeCallback);
+ if (this.session == null) {
+ this.session = session;
+ }
return session;
}
}
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/AliasCommand.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/AliasCommand.java
new file mode 100644
index 0000000..fb3b0a1
--- /dev/null
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/AliasCommand.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.karaf.shell.impl.console.osgi.secured;
+
+public class AliasCommand {
+
+ private String scope;
+ private String name;
+
+ public AliasCommand(String scope, String name) {
+ this.setScope(scope);
+ this.setName(name);
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
index 2140aab..0a23245 100644
---
a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
+++
b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
@@ -26,8 +26,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.security.auth.Subject;
@@ -38,6 +40,7 @@ import org.apache.felix.service.threadio.ThreadIO;
import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import org.apache.karaf.service.guard.tools.ACLConfigurationParser;
import org.apache.karaf.shell.api.console.Command;
+import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.impl.console.SessionFactoryImpl;
import org.apache.karaf.util.tracker.SingleServiceTracker;
import org.osgi.framework.BundleContext;
@@ -66,6 +69,7 @@ public class SecuredSessionFactoryImpl extends
SessionFactoryImpl implements Con
private Map<String, Dictionary<String, Object>> scopes = new HashMap<>();
private SingleServiceTracker<ConfigurationAdmin> configAdminTracker;
private ServiceRegistration<ConfigurationListener> registration;
+ private Map<Object, Boolean> serviceVisibleMap = new HashMap<>();
public SecuredSessionFactoryImpl(BundleContext bundleContext, ThreadIO
threadIO) throws InvalidSyntaxException {
super(threadIO);
@@ -100,15 +104,46 @@ public class SecuredSessionFactoryImpl extends
SessionFactoryImpl implements Con
@Override
protected boolean isVisible(Object service) {
+ if (this.serviceVisibleMap.get(service) != null) {
+ return this.serviceVisibleMap.get(service);
+ }
if (service instanceof Command) {
Command cmd = (Command) service;
- return isVisible(cmd.getScope(), cmd.getName());
+ boolean ret = isVisible(cmd.getScope(), cmd.getName());
+ this.serviceVisibleMap.put(service, ret);
+ return ret;
} else {
- return super.isVisible(service);
+ boolean ret = super.isVisible(service);
+ this.serviceVisibleMap.put(service, ret);
+ return ret;
}
}
public boolean isVisible(String scope, String name) {
+ boolean visible = true;
+ Dictionary<String, Object> config = getScopeConfig(scope);
+ if (config != null) {
+ visible = false;
+ List<String> roles = new ArrayList<>();
+ ACLConfigurationParser.getRolesForInvocation(name, null, null,
config, roles);
+ if (roles.isEmpty()) {
+ visible = true;
+ } else {
+ for (String role : roles) {
+ if (currentUserHasRole(role)) {
+ visible = true;
+ }
+ }
+ }
+ }
+ AliasCommand aliasCommand = findAlias(scope, name);
+ if (aliasCommand != null) {
+ visible = visible && isAliasVisible(aliasCommand.getScope(),
aliasCommand.getName());
+ }
+ return visible;
+ }
+
+ public boolean isAliasVisible(String scope, String name) {
Dictionary<String, Object> config = getScopeConfig(scope);
if (config != null) {
List<String> roles = new ArrayList<>();
@@ -123,30 +158,92 @@ public class SecuredSessionFactoryImpl extends
SessionFactoryImpl implements Con
}
return false;
}
- }
+ }
return true;
}
+
+ private AliasCommand findAlias(String scope, String name) {
+ if (session != null) {
+ Set<String> vars = ((Set<String>) session.get(null));
+ Set<String> aliases = new HashSet<>();
+ String aliasScope = null;
+ String aliasName = null;
+ for (String var : vars) {
+ Object content = session.get(var);
+ if (content != null &&
"org.apache.felix.gogo.runtime.Closure".equals(content.getClass().getName())) {
+ int index = var.indexOf(":");
+ if (index > 0) {
+ aliasScope = var.substring(0, index);
+ aliasName = var.substring(index + 1);
+ String originalCmd = content.toString();
+ index = originalCmd.indexOf(" ");
+ Object securityCmd = null;
+ if (index > 0) {
+ securityCmd =
((org.apache.felix.gogo.runtime.Closure)content)
+ .get(originalCmd.substring(0, index));
+ }
+ if (securityCmd instanceof SecuredCommand) {
+ if
(((SecuredCommand)securityCmd).getScope().equals(scope)
+ &&
((SecuredCommand)securityCmd).getName().equals(name)) {
+ return new AliasCommand(aliasScope, aliasName);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ return null;
+ }
+
+
void checkSecurity(String scope, String name, List<Object> arguments) {
+
Dictionary<String, Object> config = getScopeConfig(scope);
if (config != null) {
+ boolean passCheck = false;
if (!isVisible(scope, name)) {
throw new CommandNotFoundException(scope + ":" + name);
}
List<String> roles = new ArrayList<>();
ACLConfigurationParser.Specificity s =
ACLConfigurationParser.getRolesForInvocation(name, new Object[] {
arguments.toString() }, null, config, roles);
if (s == ACLConfigurationParser.Specificity.NO_MATCH) {
- return;
+ passCheck = true;
}
for (String role : roles) {
if (currentUserHasRole(role)) {
+ passCheck = true;
+ }
+ }
+ if (!passCheck) {
+ throw new SecurityException("Insufficient credentials.");
+ }
+ }
+ AliasCommand aliasCommand = findAlias(scope, name);
+ if (aliasCommand != null) {
+ //this is the alias
+ if (config != null) {
+ if (!isAliasVisible(aliasCommand.getScope(),
aliasCommand.getName())) {
+ throw new CommandNotFoundException(aliasCommand.getScope()
+ ":" + aliasCommand.getName());
+ }
+ List<String> roles = new ArrayList<>();
+ ACLConfigurationParser.Specificity s =
ACLConfigurationParser.getRolesForInvocation(aliasCommand.getName(), new
Object[] { arguments.toString() }, null, config, roles);
+ if (s == ACLConfigurationParser.Specificity.NO_MATCH) {
return;
}
+ for (String role : roles) {
+ if (currentUserHasRole(role)) {
+ return;
+ }
+ }
+ throw new SecurityException("Insufficient credentials.");
}
- throw new SecurityException("Insufficient credentials.");
}
+
}
+
static boolean currentUserHasRole(String requestedRole) {
String clazz;
String role;
@@ -184,6 +281,9 @@ public class SecuredSessionFactoryImpl extends
SessionFactoryImpl implements Con
return;
try {
+ synchronized(this.serviceVisibleMap) {
+ this.serviceVisibleMap.clear();
+ }
switch (event.getType()) {
case ConfigurationEvent.CM_DELETED:
removeScopeConfig(event.getPid().substring(PROXY_COMMAND_ACL_PID_PREFIX.length()));
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].