/*
* SSHTools - Java SSH2 API
*
* Copyright (C) 2002-2003 Lee David Painter and Contributors.
*
* Contributions made by:
*
* Brett Smith
* Richard Pernavas
* Erwin Bolwidt
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sshtools.common.automate;
import com.sshtools.j2ssh.SftpClient;
import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
/**
*
*
* @author $author$
* @version $Revision: 1.19 $
*/
public class RemoteIdentification {
/** */
public static final int ADD_AUTHORIZEDKEY = 1;
/** */
public static final int REMOVE_AUTHORIZEDKEY = 2;
private String defaultName;
private Vector rules = new Vector();
private Class authorizedKeysFormat;
private String defaultPath;
/** */
protected Log log = LogFactory.getLog(RemoteIdentification.class);
/**
* Creates a new RemoteIdentification object.
*
* @param defaultName
*/
public RemoteIdentification(String defaultName) {
this.defaultName = defaultName;
}
/**
*
*
* @return
*/
protected List getRules() {
return rules;
}
/**
*
*
* @return
*/
public String getDefaultName() {
return defaultName;
}
/**
*
*
* @param ident
*
* @return
*
* @throws RemoteIdentificationException
*/
public String getName(String ident) throws RemoteIdentificationException {
boolean pass = false;
Iterator it = rules.iterator();
Vector passed = new Vector();
RemoteIdentificationRule rule;
String rulename = null;
// Check all the rules
while (it.hasNext()) {
rule = (RemoteIdentificationRule) it.next();
if (rule.testRule(ident)) {
passed.add(rule);
}
}
if (passed.size() > 0) {
// Select the highest priority rule where 0=highest 10=lowest
it = passed.iterator();
RemoteIdentificationRule ret = null;
while (it.hasNext()) {
rule = (RemoteIdentificationRule) it.next();
if (ret == null) {
ret = rule;
} else {
if (rule.getPriority() < ret.getPriority()) {
ret = rule;
}
}
}
if (ret.getName() != null) {
return ret.getName();
} else {
return defaultName;
}
} else {
throw new RemoteIdentificationException(
"No rules exist to identify the remote host with ident string " +
ident);
}
}
/**
*
*
* @param rule
*/
protected void addRule(RemoteIdentificationRule rule) {
rules.add(rule);
}
/**
*
*
* @param ident
*
* @return
*/
protected boolean testRules(String ident) {
boolean pass = false;
Iterator it = rules.iterator();
RemoteIdentificationRule rule;
while (it.hasNext() && !pass) {
rule = (RemoteIdentificationRule) it.next();
pass = rule.testRule(ident);
}
return pass;
}
/**
*
*
* @param implementationClass
*/
protected void setAuthorizedKeysFormat(Class implementationClass) {
authorizedKeysFormat = implementationClass;
}
/**
*
*
* @param defaultPath
*/
protected void setAuthorizedKeysDefaultPath(String defaultPath) {
this.defaultPath = defaultPath;
}
/**
*
*
* @return
*/
public String getAuthorizedKeysDefaultPath() {
return defaultPath;
}
/**
*
*
* @return
*
* @throws RemoteIdentificationException
*/
public AuthorizedKeysFormat getAuthorizedKeysFormat()
throws RemoteIdentificationException {
try {
if (authorizedKeysFormat != null) {
return (AuthorizedKeysFormat) authorizedKeysFormat.newInstance();
} else {
throw new RemoteIdentificationException(
"There is no authorized keys format set for this remote id");
}
} catch (Exception ex) {
throw new RemoteIdentificationException("Failed to instansiate " +
authorizedKeysFormat.getName());
}
}
/**
*
*
* @param sftp
* @param serverId
* @param system
* @param username
* @param pk
* @param authorizationFile
* @param mode
*
* @return
*
* @throws RemoteIdentificationException
*/
public boolean configureUserAccess(SftpClient sftp, String serverId,
String system, String username, SshPublicKey pk,
String authorizationFile, int mode)
throws RemoteIdentificationException {
Vector keys = new Vector();
keys.add(pk);
return configureUserAccess(sftp, serverId, system, username, keys,
authorizationFile, mode);
}
/**
*
*
* @param sftp
* @param serverId
* @param system
* @param username
* @param keys
* @param authorizationFile
* @param mode
*
* @return
*
* @throws RemoteIdentificationException
*/
public boolean configureUserAccess(final SftpClient sftp,
final String serverId, String system, String username, List keys,
String authorizationFile, int mode)
throws RemoteIdentificationException {
try {
if (sftp.isClosed()) {
throw new RemoteIdentificationException(
"SFTP connection must be open");
}
if (authorizationFile == null) {
throw new RemoteIdentificationException(
"authorization file cannot be null");
}
if ((mode != ADD_AUTHORIZEDKEY) && (mode != REMOVE_AUTHORIZEDKEY)) {
throw new RemoteIdentificationException(
"Invalid configuration mode specifed in call to configureUserAccess");
}
AuthorizedKeys authorizedKeys;
authorizationFile.replace('\\', '/');
final String directory = ((authorizationFile.lastIndexOf("/") > 0)
? authorizationFile.substring(0,
authorizationFile.lastIndexOf("/") + 1) : "");
try {
// Remove the old backup - ignore the error
try {
sftp.rm(authorizationFile + ".bak");
} catch (IOException ex) {
}
// Change the current authorization file to the backup
sftp.rename(authorizationFile, authorizationFile + ".bak");
log.info("Opening existing authorized keys file from " +
authorizationFile + ".bak");
ByteArrayOutputStream out = new ByteArrayOutputStream();
sftp.get(authorizationFile + ".bak", out);
byte[] backup = out.toByteArray();
out.close();
// Obtain the current authoized keys settings
log.info("Parsing authorized keys file");
authorizedKeys = AuthorizedKeys.parse(backup, serverId, system,
new AuthorizedKeysFileLoader() {
public byte[] loadFile(String filename)
throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
sftp.get(directory + filename, out);
out.close();
return out.toByteArray();
}
});
} catch (IOException ioe) {
// Could not open so create a new file
authorizedKeys = new AuthorizedKeys();
} catch (RemoteIdentificationException rie) {
throw new RemoteIdentificationException(
"Open3SP cannot identify the remote host.\n" +
"Please email support@open3sp.org with specifying 'remote identification' in the subject and supplying the server type and the follwing data '" +
serverId + "'");
}
log.info("Updating authorized keys file");
// Check the existing keys and add any that are not present
SshPublicKey pk;
for (Iterator x = keys.iterator(); x.hasNext();) {
pk = (SshPublicKey) x.next();
if (!authorizedKeys.containsKey(pk) &&
(mode == ADD_AUTHORIZEDKEY)) {
authorizedKeys.addKey(username, pk);
} else if (authorizedKeys.containsKey(pk) &&
(mode == REMOVE_AUTHORIZEDKEY)) {
authorizedKeys.removeKey(pk);
}
}
// Verfiy that the directory exists?
log.info("Verifying directory " + directory);
int umask = sftp.umask(0022);
sftp.mkdirs(directory);
// Output the new file
log.info("Writing new authorized keys file to " +
authorizationFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Output the authorization file to a ByteArrayOutputStream
out.write(AuthorizedKeys.create(authorizedKeys, serverId, system,
new AuthorizedKeysFileSaver() {
public void saveFile(String filename, byte[] filedata)
throws IOException {
//SftpFile file = null;
ByteArrayInputStream in = null;
try {
in = new ByteArrayInputStream(filedata);
sftp.put(in, directory + filename);
} catch (IOException ex) {
log.info("Error writing public key file to server" +
filename, ex);
} finally {
if (in != null) {
in.close();
}
}
}
}));
out.close();
// Copy the new authorisation file to the server
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
sftp.umask(0133);
sftp.put(in, authorizationFile);
sftp.umask(umask);
return true;
} catch (IOException ioe) {
throw new RemoteIdentificationException(ioe.getMessage());
} catch (RemoteIdentificationException rie) {
throw new RemoteIdentificationException(
"SSHTools cannot identify the remote host.\n" +
"Please email support@sshtools.com specifying 'remote identification' in the subject, supplying the server type and the following data: '" +
serverId + "'");
}
}
}