Author: gnodet Date: Thu Dec 23 17:26:34 2010 New Revision: 1052334 URL: http://svn.apache.org/viewvc?rev=1052334&view=rev Log: [KARAF-341] When a ssh console is invoked, the code should be run under the credentials of the authenticated user
Added: karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasPasswordAuthenticator.java Modified: karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java karaf/trunk/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml Added: karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasPasswordAuthenticator.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasPasswordAuthenticator.java?rev=1052334&view=auto ============================================================================== --- karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasPasswordAuthenticator.java (added) +++ karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/KarafJaasPasswordAuthenticator.java Thu Dec 23 17:26:34 2010 @@ -0,0 +1,77 @@ +/* + * 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.ssh; + +import java.io.IOException; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginContext; + +import org.apache.sshd.common.Session; +import org.apache.sshd.server.PasswordAuthenticator; +import org.apache.sshd.server.session.ServerSession; + +/** + * TODO Add javadoc + * + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class KarafJaasPasswordAuthenticator implements PasswordAuthenticator { + + public static final Session.AttributeKey<Subject> SUBJECT_ATTRIBUTE_KEY = new Session.AttributeKey<Subject>(); + + private String domain; + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public boolean authenticate(final String username, final String password, final ServerSession session) { + try { + Subject subject = new Subject(); + LoginContext loginContext = new LoginContext(domain, subject, new CallbackHandler() { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof NameCallback) { + ((NameCallback) callbacks[i]).setName(username); + } else if (callbacks[i] instanceof PasswordCallback) { + ((PasswordCallback) callbacks[i]).setPassword(password.toCharArray()); + } else { + throw new UnsupportedCallbackException(callbacks[i]); + } + } + } + }); + loginContext.login(); + session.setAttribute(SUBJECT_ATTRIBUTE_KEY, loginContext.getSubject()); + return true; + } catch (Exception e) { + return false; + } + } + +} Modified: karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java?rev=1052334&r1=1052333&r2=1052334&view=diff ============================================================================== --- karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java (original) +++ karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellCommandFactory.java Thu Dec 23 17:26:34 2010 @@ -23,6 +23,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import javax.security.auth.Subject; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; @@ -30,6 +33,8 @@ import org.apache.sshd.server.Command; import org.apache.sshd.server.CommandFactory; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; +import org.apache.sshd.server.SessionAware; +import org.apache.sshd.server.session.ServerSession; public class ShellCommandFactory implements CommandFactory { @@ -43,13 +48,14 @@ public class ShellCommandFactory impleme return new ShellCommand(command); } - public class ShellCommand implements Command { + public class ShellCommand implements Command, SessionAware { private String command; private InputStream in; private OutputStream out; private OutputStream err; private ExitCallback callback; + private ServerSession session; public ShellCommand(String command) { this.command = command; @@ -71,10 +77,28 @@ public class ShellCommandFactory impleme this.callback = callback; } + public void setSession(ServerSession session) { + this.session = session; + } + public void start(final Environment env) throws IOException { try { - CommandSession session = commandProcessor.createSession(in, new PrintStream(out), new PrintStream(err)); - session.execute(command); + final CommandSession session = commandProcessor.createSession(in, new PrintStream(out), new PrintStream(err)); + Subject subject = this.session != null ? this.session.getAttribute(KarafJaasPasswordAuthenticator.SUBJECT_ATTRIBUTE_KEY) : null; + if (subject != null) { + try { + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { + public Object run() throws Exception { + session.execute(command); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw e.getException(); + } + } else { + session.execute(command); + } } catch (Exception e) { throw (IOException) new IOException("Unable to start shell").initCause(e); } finally { Modified: karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java URL: http://svn.apache.org/viewvc/karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java?rev=1052334&r1=1052333&r2=1052334&view=diff ============================================================================== --- karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java (original) +++ karaf/trunk/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java Thu Dec 23 17:26:34 2010 @@ -25,24 +25,22 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.security.PrivilegedAction; import java.util.List; import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Callable; +import javax.security.auth.Subject; import jline.Terminal; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Function; -import org.apache.karaf.shell.console.Completer; -import org.apache.karaf.shell.console.completer.AggregateCompleter; import org.apache.karaf.shell.console.jline.Console; import org.apache.sshd.common.Factory; import org.apache.sshd.server.Command; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; -import org.apache.sshd.server.Signal; -import org.apache.sshd.server.SignalListener; +import org.apache.sshd.server.SessionAware; +import org.apache.sshd.server.session.ServerSession; import org.osgi.service.blueprint.container.ReifiedType; /** @@ -62,7 +60,7 @@ public class ShellFactoryImpl implements return new ShellImpl(); } - public class ShellImpl implements Command + public class ShellImpl implements Command, SessionAware { private InputStream in; @@ -72,6 +70,8 @@ public class ShellFactoryImpl implements private ExitCallback callback; + private ServerSession session; + private boolean closed; public void setInputStream(final InputStream in) { @@ -90,6 +90,10 @@ public class ShellFactoryImpl implements this.callback = callback; } + public void setSession(ServerSession session) { + this.session = session; + } + public void start(final Environment env) throws IOException { try { final Terminal terminal = new SshTerminal(env); @@ -119,7 +123,25 @@ public class ShellFactoryImpl implements } }); session.put(".jline.terminal", terminal); - new Thread(console).start(); + new Thread(console) { + @Override + public void run() { + Subject subject = ShellImpl.this.session != null ? ShellImpl.this.session.getAttribute(KarafJaasPasswordAuthenticator.SUBJECT_ATTRIBUTE_KEY) : null; + if (subject != null) { + Subject.doAs(subject, new PrivilegedAction<Object>() { + public Object run() { + doRun(); + return null; + } + }); + } else { + doRun(); + } + } + protected void doRun() { + super.run(); + } + }.start(); } catch (Exception e) { throw (IOException) new IOException("Unable to start shell").initCause(e); } Modified: karaf/trunk/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml URL: http://svn.apache.org/viewvc/karaf/trunk/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml?rev=1052334&r1=1052333&r2=1052334&view=diff ============================================================================== --- karaf/trunk/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml (original) +++ karaf/trunk/shell/ssh/src/main/resources/OSGI-INF/blueprint/shell-ssh.xml Thu Dec 23 17:26:34 2010 @@ -82,7 +82,7 @@ <bean id="keyPairProvider" class="org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider"> <property name="path" value="${hostKey}"/> </bean> - <bean id="passwordAuthenticator" class="org.apache.sshd.server.jaas.JaasPasswordAuthenticator"> + <bean id="passwordAuthenticator" class="org.apache.karaf.shell.ssh.KarafJaasPasswordAuthenticator"> <property name="domain" value="${sshRealm}"/> </bean>