001 /* 002 * Copyright (C) 2003-2009 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 package org.crsh.ssh.term; 020 021 import org.apache.sshd.SshServer; 022 import org.apache.sshd.common.Session; 023 import org.apache.sshd.server.PasswordAuthenticator; 024 import org.apache.sshd.server.session.ServerSession; 025 import org.crsh.plugin.PluginContext; 026 import org.crsh.auth.AuthenticationPlugin; 027 import org.crsh.ssh.term.scp.SCPCommandFactory; 028 import org.crsh.term.TermLifeCycle; 029 import org.crsh.term.spi.TermIOHandler; 030 import org.slf4j.Logger; 031 import org.slf4j.LoggerFactory; 032 033 import java.net.URL; 034 035 /** 036 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> 037 * @version $Revision$ 038 */ 039 public class SSHLifeCycle extends TermLifeCycle { 040 041 /** . */ 042 public static final Session.AttributeKey<String> USERNAME = new Session.AttributeKey<java.lang.String>(); 043 044 /** . */ 045 public static final Session.AttributeKey<String> PASSWORD = new Session.AttributeKey<java.lang.String>(); 046 047 /** . */ 048 private final Logger log = LoggerFactory.getLogger(SSHLifeCycle.class); 049 050 /** . */ 051 private SshServer server; 052 053 /** . */ 054 private int port; 055 056 /** . */ 057 private URL keyURL; 058 059 /** . */ 060 private String authentication; 061 062 public SSHLifeCycle(PluginContext context) { 063 super(context); 064 } 065 066 public int getPort() { 067 return port; 068 } 069 070 public void setPort(int port) { 071 this.port = port; 072 } 073 074 public URL getKeyURL() { 075 return keyURL; 076 } 077 078 public void setKeyURL(URL keyURL) { 079 this.keyURL = keyURL; 080 } 081 082 public String getAuthentication() { 083 return authentication; 084 } 085 086 public void setAuthentication(String authentication) { 087 this.authentication = authentication; 088 } 089 090 @Override 091 protected void doInit() { 092 try { 093 094 // 095 TermIOHandler handler = getHandler(); 096 097 // 098 SshServer server = SshServer.setUpDefaultServer(); 099 server.setPort(port); 100 server.setShellFactory(new CRaSHCommandFactory(handler)); 101 server.setCommandFactory(new SCPCommandFactory(getContext())); 102 server.setKeyPairProvider(new URLKeyPairProvider(keyURL)); 103 104 // We never authenticate by default 105 AuthenticationPlugin plugin = new AuthenticationPlugin() { 106 public String getName() { 107 return "null"; 108 } 109 public boolean authenticate(String username, String password) throws Exception { 110 return false; 111 } 112 }; 113 114 // Lookup for an authentication plugin 115 if (authentication != null) { 116 for (AuthenticationPlugin authenticationPlugin : getContext().getPlugins(AuthenticationPlugin.class)) { 117 if (authentication.equals(authenticationPlugin.getName())) { 118 plugin = authenticationPlugin; 119 break; 120 } 121 } 122 } 123 124 // 125 final AuthenticationPlugin authPlugin = plugin; 126 127 // 128 server.setPasswordAuthenticator(new PasswordAuthenticator() { 129 public boolean authenticate(String _username, String _password, ServerSession session) { 130 boolean auth; 131 if (authPlugin != null) 132 { 133 try { 134 log.debug("Using authentication plugin " + authPlugin + " to authenticate user " + _username); 135 auth = authPlugin.authenticate(_username, _password); 136 } catch (Exception e) { 137 log.error("Exception authenticating user " + _username + " in authentication plugin: " + authPlugin, e); 138 return false; 139 } 140 } 141 else 142 { 143 // Say ok as this will be used later for performing an other kind of authentication 144 auth = true; 145 } 146 147 // We store username and password in session for later reuse 148 session.setAttribute(USERNAME, _username); 149 session.setAttribute(PASSWORD, _password); 150 151 // 152 return auth; 153 } 154 }); 155 156 // 157 log.info("About to start CRaSSHD"); 158 server.start(); 159 log.info("CRaSSHD started on port " + port); 160 161 // 162 this.server = server; 163 } 164 catch (Throwable e) { 165 log.error("Could not start CRaSSHD", e); 166 } 167 } 168 169 @Override 170 protected void doDestroy() { 171 if (server != null) { 172 try { 173 server.stop(); 174 } 175 catch (InterruptedException e) { 176 log.debug("Got an interruption when stopping server", e); 177 } 178 } 179 } 180 }