001 /* 002 * Copyright (C) 2012 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.crsh.vfs.Resource; 031 032 import java.util.logging.Level; 033 import java.util.logging.Logger; 034 035 public class SSHLifeCycle extends TermLifeCycle { 036 037 /** . */ 038 public static final Session.AttributeKey<String> USERNAME = new Session.AttributeKey<java.lang.String>(); 039 040 /** . */ 041 public static final Session.AttributeKey<String> PASSWORD = new Session.AttributeKey<java.lang.String>(); 042 043 /** . */ 044 private final Logger log = Logger.getLogger(SSHLifeCycle.class.getName()); 045 046 /** . */ 047 private SshServer server; 048 049 /** . */ 050 private int port; 051 052 /** . */ 053 private Resource key; 054 055 /** . */ 056 private String authentication; 057 058 public SSHLifeCycle(PluginContext context) { 059 super(context); 060 } 061 062 public int getPort() { 063 return port; 064 } 065 066 public void setPort(int port) { 067 this.port = port; 068 } 069 070 public Resource getKey() { 071 return key; 072 } 073 074 public void setKey(Resource key) { 075 this.key = key; 076 } 077 078 public String getAuthentication() { 079 return authentication; 080 } 081 082 public void setAuthentication(String authentication) { 083 this.authentication = authentication; 084 } 085 086 @Override 087 protected void doInit() { 088 try { 089 090 // 091 TermIOHandler handler = getHandler(); 092 093 // 094 SshServer server = SshServer.setUpDefaultServer(); 095 server.setPort(port); 096 server.setShellFactory(new CRaSHCommandFactory(handler)); 097 server.setCommandFactory(new SCPCommandFactory(getContext())); 098 server.setKeyPairProvider(new URLKeyPairProvider(key)); 099 100 // We never authenticate by default 101 AuthenticationPlugin plugin = new AuthenticationPlugin() { 102 public String getName() { 103 return "null"; 104 } 105 public boolean authenticate(String username, String password) throws Exception { 106 return false; 107 } 108 }; 109 110 // Lookup for an authentication plugin 111 if (authentication != null) { 112 for (AuthenticationPlugin authenticationPlugin : getContext().getPlugins(AuthenticationPlugin.class)) { 113 if (authentication.equals(authenticationPlugin.getName())) { 114 plugin = authenticationPlugin; 115 break; 116 } 117 } 118 } 119 120 // 121 final AuthenticationPlugin authPlugin = plugin; 122 123 // 124 server.setPasswordAuthenticator(new PasswordAuthenticator() { 125 public boolean authenticate(String _username, String _password, ServerSession session) { 126 boolean auth; 127 try { 128 log.log(Level.FINE, "Using authentication plugin " + authPlugin + " to authenticate user " + _username); 129 auth = authPlugin.authenticate(_username, _password); 130 } catch (Exception e) { 131 log.log(Level.SEVERE, "Exception authenticating user " + _username + " in authentication plugin: " + authPlugin, e); 132 return false; 133 } 134 135 // We store username and password in session for later reuse 136 session.setAttribute(USERNAME, _username); 137 session.setAttribute(PASSWORD, _password); 138 139 // 140 return auth; 141 } 142 }); 143 144 // 145 log.log(Level.INFO, "About to start CRaSSHD"); 146 server.start(); 147 log.log(Level.INFO, "CRaSSHD started on port " + port); 148 149 // 150 this.server = server; 151 } 152 catch (Throwable e) { 153 log.log(Level.SEVERE, "Could not start CRaSSHD", e); 154 } 155 } 156 157 @Override 158 protected void doDestroy() { 159 if (server != null) { 160 try { 161 server.stop(); 162 } 163 catch (InterruptedException e) { 164 log.log(Level.FINE, "Got an interruption when stopping server", e); 165 } 166 } 167 } 168 }