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]>'].

Reply via email to