userauth/ reformat

This commit is contained in:
Shikhar Bhushan
2010-03-02 00:04:18 +01:00
parent a1ab7bdc8f
commit 10067c7baa
18 changed files with 103 additions and 81 deletions

View File

@@ -41,15 +41,11 @@ import net.schmizz.sshj.userauth.method.AuthMethod;
import java.util.Deque;
/**
* User authentication API
*
* @see rfc4252
*/
/** User authentication API. See RFC 4252. */
public interface UserAuth {
/**
* Attempt to authenticate {@code username} using each of {@link methods} in order. {@code nextService} is the
* Attempt to authenticate {@code username} using each of {@code methods} in order. {@code nextService} is the
* {@link net.schmizz.sshj.Service} that will be enabled on successful authentication.
* <p/>
* Authentication fails if there are no method available, i.e. if all the method failed or there were method
@@ -66,8 +62,8 @@ public interface UserAuth {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
void authenticate(String username, Service nextService, Iterable<AuthMethod> methods) throws UserAuthException,
TransportException;
void authenticate(String username, Service nextService, Iterable<AuthMethod> methods)
throws UserAuthException, TransportException;
/**
* Returns the authentication banner (if any). In some cases this is available even before the first authentication
@@ -77,14 +73,14 @@ public interface UserAuth {
*/
String getBanner();
/** Returns saved exceptions that might have been ignored because there were more authentication method available. */
/** @return Saved exceptions that might have been ignored because there were more authentication method available. */
Deque<UserAuthException> getSavedExceptions();
/** Returns the {@code timeout} for a method to successfully authenticate before it is abandoned. */
/** @return The {@code timeout} for a method to successfully authenticate before it is abandoned. */
int getTimeout();
/**
* Returns whether authentication was partially successful. Some server's may be configured to require multiple
* @return Whether authentication was partially successful. Some server's may be configured to require multiple
* authentications; and this value will be {@code true} if at least one of the method supplied succeeded.
*/
boolean hadPartialSuccess();

View File

@@ -40,7 +40,8 @@ import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.SSHException;
/** User authentication exception */
public class UserAuthException extends SSHException {
public class UserAuthException
extends SSHException {
public static final ExceptionChainer<UserAuthException> chainer = new ExceptionChainer<UserAuthException>() {

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.userauth;
@@ -54,7 +34,9 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
/** {@link UserAuth} implementation. */
public class UserAuthImpl extends AbstractService implements UserAuth, AuthParams {
public class UserAuthImpl
extends AbstractService
implements UserAuth, AuthParams {
private final Set<String> allowed = new HashSet<String>();
@@ -158,7 +140,8 @@ public class UserAuthImpl extends AbstractService implements UserAuth, AuthParam
}
@Override
public void handle(Message msg, SSHPacket buf) throws SSHException {
public void handle(Message msg, SSHPacket buf)
throws SSHException {
if (!msg.in(50, 80)) // ssh-userauth packets have message numbers between 50-80
throw new TransportException(DisconnectReason.PROTOCOL_ERROR);
@@ -198,7 +181,8 @@ public class UserAuthImpl extends AbstractService implements UserAuth, AuthParam
banner = buf.readString();
}
private void gotFailure(SSHPacket buf) throws UserAuthException, TransportException {
private void gotFailure(SSHPacket buf)
throws UserAuthException, TransportException {
allowed.clear();
allowed.addAll(Arrays.<String>asList(buf.readString().split(",")));
partialSuccess |= buf.readBoolean();
@@ -216,7 +200,8 @@ public class UserAuthImpl extends AbstractService implements UserAuth, AuthParam
result.set(true);
}
private void gotUnknown(Message msg, SSHPacket buf) throws SSHException {
private void gotUnknown(Message msg, SSHPacket buf)
throws SSHException {
if (currentMethod == null || result == null) {
trans.sendUnimplemented();
return;
@@ -239,7 +224,8 @@ public class UserAuthImpl extends AbstractService implements UserAuth, AuthParam
savedEx.push(e);
}
private boolean tryWith(AuthMethod meth) throws UserAuthException, TransportException {
private boolean tryWith(AuthMethod meth)
throws UserAuthException, TransportException {
currentMethod = meth;
result.clear();
meth.init(this);

View File

@@ -40,10 +40,13 @@ import net.schmizz.sshj.userauth.password.PasswordFinder;
import java.io.File;
/** A file key provider is initialized with a location of */
public interface FileKeyProvider extends KeyProvider {
public interface FileKeyProvider
extends KeyProvider {
enum Format {
PKCS8, OpenSSH, Unknown
PKCS8,
OpenSSH,
Unknown
}
void init(File location);

View File

@@ -42,7 +42,8 @@ import java.security.PrivateKey;
import java.security.PublicKey;
/** A {@link KeyProvider} wrapper around {@link java.security.KeyPair} */
public class KeyPairWrapper implements KeyProvider {
public class KeyPairWrapper
implements KeyProvider {
private final KeyPair kp;
private final KeyType type;

View File

@@ -45,12 +45,15 @@ import java.security.PublicKey;
public interface KeyProvider {
/** Returns the private key. */
PrivateKey getPrivate() throws IOException;
PrivateKey getPrivate()
throws IOException;
/** Returns the public key. */
PublicKey getPublic() throws IOException;
PublicKey getPublic()
throws IOException;
/** Returns the {@link KeyType}. */
KeyType getType() throws IOException;
KeyType getType()
throws IOException;
}

View File

@@ -35,7 +35,8 @@ public class KeyProviderUtil {
*
* @throws java.io.IOException
*/
public static FileKeyProvider.Format detectKeyFileFormat(File location) throws IOException {
public static FileKeyProvider.Format detectKeyFileFormat(File location)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(location));
String firstLine = br.readLine();
IOUtils.closeQuietly(br);
@@ -51,7 +52,7 @@ public class KeyProviderUtil {
/*
* TODO: Tectia, PuTTY (.ppk) ...
*/
return FileKeyProvider.Format.OpenSSH;
return FileKeyProvider.Format.Unknown;
}
}

View File

@@ -52,9 +52,11 @@ import java.security.PublicKey;
*
* @see PKCS8KeyFile
*/
public class OpenSSHKeyFile extends PKCS8KeyFile {
public class OpenSSHKeyFile
extends PKCS8KeyFile {
public static class Factory implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
public FileKeyProvider create() {
return new OpenSSHKeyFile();
@@ -68,7 +70,8 @@ public class OpenSSHKeyFile extends PKCS8KeyFile {
private PublicKey pubKey;
@Override
public PublicKey getPublic() throws IOException {
public PublicKey getPublic()
throws IOException {
return pubKey != null ? pubKey : super.getPublic();
}

View File

@@ -55,9 +55,11 @@ import java.security.PrivateKey;
import java.security.PublicKey;
/** Represents a PKCS8-encoded key file. This is the format used by OpenSSH and OpenSSL. */
public class PKCS8KeyFile implements FileKeyProvider {
public class PKCS8KeyFile
implements FileKeyProvider {
public static class Factory implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
public FileKeyProvider create() {
return new PKCS8KeyFile();
}
@@ -77,15 +79,18 @@ public class PKCS8KeyFile implements FileKeyProvider {
protected char[] passphrase; // for blanking out
public PrivateKey getPrivate() throws IOException {
public PrivateKey getPrivate()
throws IOException {
return kp != null ? kp.getPrivate() : (kp = readKeyPair()).getPrivate();
}
public PublicKey getPublic() throws IOException {
public PublicKey getPublic()
throws IOException {
return kp != null ? kp.getPublic() : (kp = readKeyPair()).getPublic();
}
public KeyType getType() throws IOException {
public KeyType getType()
throws IOException {
return type != null ? type : (type = KeyType.fromKey(getPublic()));
}
@@ -111,7 +116,8 @@ public class PKCS8KeyFile implements FileKeyProvider {
};
}
protected KeyPair readKeyPair() throws IOException {
protected KeyPair readKeyPair()
throws IOException {
KeyPair kp = null;
org.bouncycastle.openssl.PasswordFinder pFinder = makeBouncyPasswordFinder();
PEMReader r = null;

View File

@@ -44,14 +44,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** This abstract class for {@link AuthMethod} implements common or default functionality. */
public abstract class AbstractAuthMethod implements AuthMethod {
public abstract class AbstractAuthMethod
implements AuthMethod {
/** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass());
private final String name;
/** {@link net.schmizz.sshj.userauth.AuthParams} useful for building request. */
/** {@link AuthParams} useful for building request. */
protected AuthParams params;
/** Create with the {@code name} of this authentication method. */
@@ -63,7 +64,8 @@ public abstract class AbstractAuthMethod implements AuthMethod {
return name;
}
public void handle(Message msg, SSHPacket buf) throws UserAuthException, TransportException {
public void handle(Message msg, SSHPacket buf)
throws UserAuthException, TransportException {
throw new UserAuthException("Unknown packet received during " + getName() + " auth: " + msg);
}
@@ -71,7 +73,8 @@ public abstract class AbstractAuthMethod implements AuthMethod {
this.params = params;
}
public void request() throws UserAuthException, TransportException {
public void request()
throws UserAuthException, TransportException {
params.getTransport().write(buildReq());
}
@@ -80,10 +83,11 @@ public abstract class AbstractAuthMethod implements AuthMethod {
}
/**
* Builds a {@link net.schmizz.sshj.common.SSHPacket} containing the fields common to all authentication method.
* Method-specific fields can further be put into this buffer.
* Builds a {@link SSHPacket} containing the fields common to all authentication method. Method-specific fields can
* further be put into this buffer.
*/
protected SSHPacket buildReq() throws UserAuthException {
protected SSHPacket buildReq()
throws UserAuthException {
return new SSHPacket(Message.USERAUTH_REQUEST) // SSH_MSG_USERAUTH_REQUEST
.putString(params.getUsername()) // username goes first
.putString(params.getNextServiceName()) // the service that we'd like on success

View File

@@ -42,7 +42,8 @@ import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
// TODO check if this even works...!
/** Implements the {@code hostbased} SSH authentication method. */
public class AuthHostbased extends KeyedAuthMethod {
public class AuthHostbased
extends KeyedAuthMethod {
protected final String hostname;
protected final String hostuser;
@@ -59,7 +60,8 @@ public class AuthHostbased extends KeyedAuthMethod {
}
@Override
protected SSHPacket buildReq() throws UserAuthException {
protected SSHPacket buildReq()
throws UserAuthException {
SSHPacket req = putPubKey(super.buildReq());
req.putString(hostname == null ? params.getTransport().getRemoteHost() : hostname) //
.putString(hostuser);

View File

@@ -45,7 +45,8 @@ import net.schmizz.sshj.userauth.UserAuthException;
*
* @see net.schmizz.sshj.userauth.UserAuth
*/
public interface AuthMethod extends SSHPacketHandler {
public interface AuthMethod
extends SSHPacketHandler {
/** Returns assigned name of this authentication method */
String getName();
@@ -61,7 +62,8 @@ public interface AuthMethod extends SSHPacketHandler {
*
* @throws TransportException
*/
void request() throws UserAuthException, TransportException;
void request()
throws UserAuthException, TransportException;
/** Returns whether authentication should be reattempted if it failed. */
boolean shouldRetry();

View File

@@ -40,7 +40,8 @@ package net.schmizz.sshj.userauth.method;
* service requested. This method generally fails and is typically used to find out the method allowed by an SSH server
* (sent as part of the {@code SSH_MSG_USERAUTH_FAILURE} packet)
*/
public class AuthNone extends AbstractAuthMethod {
public class AuthNone
extends AbstractAuthMethod {
AuthNone() {
super("none");

View File

@@ -45,7 +45,8 @@ import net.schmizz.sshj.userauth.password.PasswordFinder;
import net.schmizz.sshj.userauth.password.Resource;
/** Implements the {@code password} authentication method. Password-change request handling is not currently supported. */
public class AuthPassword extends AbstractAuthMethod {
public class AuthPassword
extends AbstractAuthMethod {
private final PasswordFinder pwdf;
private Resource resource;
@@ -63,7 +64,8 @@ public class AuthPassword extends AbstractAuthMethod {
}
@Override
public SSHPacket buildReq() throws UserAuthException {
public SSHPacket buildReq()
throws UserAuthException {
log.info("Requesting password for " + resource);
char[] password = pwdf.reqPassword(resource);
if (password == null)
@@ -75,7 +77,8 @@ public class AuthPassword extends AbstractAuthMethod {
}
@Override
public void handle(Message cmd, SSHPacket buf) throws UserAuthException, TransportException {
public void handle(Message cmd, SSHPacket buf)
throws UserAuthException, TransportException {
if (cmd == Message.USERAUTH_60)
throw new UserAuthException("Password change request received; unsupported operation");
else

View File

@@ -51,7 +51,8 @@ import java.io.IOException;
* request signed with the private key. Therefore, private keys are not requested from the associated {@link
* KeyProvider} unless needed.
*/
public class AuthPublickey extends KeyedAuthMethod {
public class AuthPublickey
extends KeyedAuthMethod {
/** Initialize this method with the provider for public and private key. */
public AuthPublickey(KeyProvider kProv) {
@@ -60,7 +61,8 @@ public class AuthPublickey extends KeyedAuthMethod {
/** Internal use. */
@Override
public void handle(Message cmd, SSHPacket buf) throws UserAuthException, TransportException {
public void handle(Message cmd, SSHPacket buf)
throws UserAuthException, TransportException {
if (cmd == Message.USERAUTH_60)
sendSignedReq();
else
@@ -76,7 +78,8 @@ public class AuthPublickey extends KeyedAuthMethod {
*
* @throws UserAuthException
*/
private SSHPacket buildReq(boolean signed) throws UserAuthException {
private SSHPacket buildReq(boolean signed)
throws UserAuthException {
try {
kProv.getPublic();
} catch (IOException ioe) {
@@ -91,14 +94,16 @@ public class AuthPublickey extends KeyedAuthMethod {
* @throws UserAuthException
* @throws TransportException
*/
private void sendSignedReq() throws UserAuthException, TransportException {
private void sendSignedReq()
throws UserAuthException, TransportException {
log.debug("Sending signed request");
params.getTransport().write(putSig(buildReq(true)));
}
/** Builds a feeler request (sans signature). */
@Override
protected SSHPacket buildReq() throws UserAuthException {
protected SSHPacket buildReq()
throws UserAuthException {
return buildReq(false);
}

View File

@@ -47,7 +47,8 @@ import java.io.IOException;
import java.security.PrivateKey;
import java.security.PublicKey;
public abstract class KeyedAuthMethod extends AbstractAuthMethod {
public abstract class KeyedAuthMethod
extends AbstractAuthMethod {
protected KeyProvider kProv;
public KeyedAuthMethod(String name, KeyProvider kProv) {
@@ -55,7 +56,8 @@ public abstract class KeyedAuthMethod extends AbstractAuthMethod {
this.kProv = kProv;
}
protected SSHPacket putPubKey(SSHPacket reqBuf) throws UserAuthException {
protected SSHPacket putPubKey(SSHPacket reqBuf)
throws UserAuthException {
PublicKey key;
try {
key = kProv.getPublic();
@@ -70,7 +72,8 @@ public abstract class KeyedAuthMethod extends AbstractAuthMethod {
return reqBuf;
}
protected SSHPacket putSig(SSHPacket reqBuf) throws UserAuthException {
protected SSHPacket putSig(SSHPacket reqBuf)
throws UserAuthException {
PrivateKey key;
try {
key = kProv.getPrivate();

View File

@@ -15,7 +15,8 @@
*/
package net.schmizz.sshj.userauth.password;
public class AccountResource extends Resource<String> {
public class AccountResource
extends Resource<String> {
public AccountResource(String user, String host) {
super(user + "@" + host);

View File

@@ -15,7 +15,8 @@
*/
package net.schmizz.sshj.userauth.password;
public class PrivateKeyFileResource extends Resource<String> {
public class PrivateKeyFileResource
extends Resource<String> {
public PrivateKeyFileResource(String path) {
super(path);