All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sshtools.publickey.PublicKeySubsystem Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2003-2016 SSHTOOLS Limited. All Rights Reserved.
 *
 * For product documentation visit https://www.sshtools.com/
 *
 * This file is part of J2SSH Maverick.
 *
 * J2SSH Maverick is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * J2SSH Maverick 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 J2SSH Maverick.  If not, see .
 */
package com.sshtools.publickey;

import java.io.IOException;
import java.util.Vector;

import com.sshtools.ssh.Packet;
import com.sshtools.ssh.SshException;
import com.sshtools.ssh.SubsystemChannel;
import com.sshtools.ssh.components.SshPublicKey;
import com.sshtools.ssh2.Ssh2Session;
import com.sshtools.util.ByteArrayReader;

/**
 * This class implements version 1 of the public key subsystem.
 * 
 * @author Lee David Painter
 */
public class PublicKeySubsystem extends SubsystemChannel {

	static final int SSH_PUBLICKEY_SUCCESS = 0;
	static final int SSH_PUBLICKEY_ACCESS_DENIED = 1;
	static final int SSH_PUBLICKEY_STORAGE_EXCEEDED = 2;
	static final int SSH_PUBLICKEY_VERSION_NOT_SUPPORTED = 3;
	static final int SSH_PUBLICKEY_KEY_NOT_FOUND = 4;
	static final int SSH_PUBLICKEY_KEY_NOT_SUPPORTED = 5;
	static final int SSH_PUBLICKEY_KEY_ALREADY_PRESENT = 6;
	static final int SSH_PUBLICKEY_GENERAL_FAILURE = 7;
	static final int SSH_PUBLICKEY_REQUEST_NOT_SUPPORTED = 8;

	static final int VERSION_1 = 1;
	static final int VERSION_2 = 2;

	int version;

	public PublicKeySubsystem(Ssh2Session session) throws SshException {
		super(session);

		try {
			if (!session.startSubsystem("[email protected]")) {
				throw new SshException(
						"The remote side failed to start the publickey subsystem",
						SshException.CHANNEL_FAILURE);
			}

			Packet msg = createPacket();
			msg.writeString("version");
			msg.writeInt(VERSION_1);

			sendMessage(msg);

			ByteArrayReader response = new ByteArrayReader(nextMessage());

			try {
				// String v =
				response.readString();

				int serverVersion = (int) response.readInt();
				version = Math.min(serverVersion, VERSION_1);
			} finally {
				try {
					response.close();
				} catch (IOException e) {
				}
			}
		} catch (IOException ex) {
			throw new SshException(SshException.INTERNAL_ERROR, ex);
		}

	}

	/**
	 * Add a public key to the users list of acceptable keys.
	 * 
	 * @param key
	 * @param comment
	 * @throws SshException
	 * @throws PublicKeyStatusException
	 */
	public void add(SshPublicKey key, String comment) throws SshException,
			PublicKeySubsystemException {

		try {
			Packet msg = createPacket();
			msg.writeString("add");
			msg.writeString(comment);
			msg.writeString(key.getAlgorithm());
			msg.writeBinaryString(key.getEncoded());

			sendMessage(msg);

			readStatusResponse();

		} catch (IOException ex) {
			throw new SshException(ex);
		}

	}

	/**
	 * Remove a public key from the users list of acceptable keys.
	 * 
	 * @param key
	 * @throws SshException
	 * @throws PublicKeyStatusException
	 */
	public void remove(SshPublicKey key) throws SshException,
			PublicKeySubsystemException {

		try {

			Packet msg = createPacket();
			msg.writeString("remove");
			msg.writeString(key.getAlgorithm());
			msg.writeBinaryString(key.getEncoded());

			sendMessage(msg);

			readStatusResponse();

		} catch (IOException ex) {
			throw new SshException(ex);
		}
	}

	/**
	 * List all of the users acceptable keys.
	 * 
	 * @return SshPublicKey[]
	 */
	public SshPublicKey[] list() throws SshException,
			PublicKeySubsystemException {

		try {

			Packet msg = createPacket();
			msg.writeString("list");

			sendMessage(msg);

			Vector keys = new Vector();

			while (true) {
				ByteArrayReader response = new ByteArrayReader(nextMessage());

				try {
					String type = response.readString();

					if (type.equals("publickey")) {
						@SuppressWarnings("unused")
						String comment = response.readString();
						String algorithm = response.readString();
						keys.addElement(SshPublicKeyFileFactory
								.decodeSSH2PublicKey(algorithm,
										response.readBinaryString()));

					} else if (type.equals("status")) {
						int status = (int) response.readInt();
						String desc = response.readString();

						if (status != PublicKeySubsystemException.SUCCESS) {
							throw new PublicKeySubsystemException(status, desc);
						}
						SshPublicKey[] array = new SshPublicKey[keys.size()];
						keys.copyInto(array);

						return array;

					} else {
						throw new SshException(
								"The server sent an invalid response to a list command",
								SshException.PROTOCOL_VIOLATION);
					}
				} finally {
					try {
						response.close();
					} catch (IOException e) {
					}
				}
			}
		} catch (IOException ex) {
			throw new SshException(ex);
		}

	}

	/**
	 * Associate a command with an accepted public key. The request will fail if
	 * the public key is not currently in the users acceptable list. Also some
	 * server implementations may choose not to support this feature.
	 * 
	 * @param key
	 * @param command
	 * @throws SshException
	 * @throws PublicKeyStatusException
	 */
	public void associateCommand(SshPublicKey key, String command)
			throws SshException, PublicKeySubsystemException {

		try {

			Packet msg = createPacket();
			msg.writeString("command");
			msg.writeString(key.getAlgorithm());
			msg.writeBinaryString(key.getEncoded());
			msg.writeString(command);

			sendMessage(msg);

			readStatusResponse();

		} catch (IOException ex) {
			throw new SshException(ex);
		}

	}

	/**
	 * Read a status response and throw an exception if an error has occurred.
	 * 
	 * @throws SshException
	 * @throws PublicKeyStatusException
	 */
	void readStatusResponse() throws SshException, PublicKeySubsystemException {

		ByteArrayReader msg = new ByteArrayReader(nextMessage());

		try {

			msg.readString();
			int status = (int) msg.readInt();
			String desc = msg.readString();

			if (status != PublicKeySubsystemException.SUCCESS) {
				throw new PublicKeySubsystemException(status, desc);
			}
		} catch (IOException ex) {
			throw new SshException(ex);
		} finally {
			try {
				msg.close();
			} catch (IOException e) {
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy