keyboard-interactive auth!

This commit is contained in:
Shikhar Bhushan
2010-05-22 03:06:40 +01:00
parent a7ccccaacf
commit 252fcebeac
3 changed files with 201 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2010 Shikhar Bhushan
*
* Licensed 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.method;
import net.schmizz.sshj.common.Message;
import net.schmizz.sshj.common.SSHPacket;
import net.schmizz.sshj.transport.TransportException;
import net.schmizz.sshj.userauth.AuthParams;
import net.schmizz.sshj.userauth.UserAuthException;
import net.schmizz.sshj.userauth.password.AccountResource;
import net.schmizz.sshj.userauth.password.Resource;
import java.util.ArrayList;
import java.util.List;
/** Implements the {@code keyboard-interactive} authentication method. */
public class AuthChallengeResponse
extends AbstractAuthMethod {
private final ChallengeResponseProvider provider;
private Resource resource;
public AuthChallengeResponse(ChallengeResponseProvider provider) {
super("keyboard-interactive");
this.provider = provider;
}
public AuthChallengeResponse(ChallengeResponseProvider provider, List<String> submethods) {
this(provider);
}
@Override
public void init(AuthParams params) {
super.init(params);
resource = new AccountResource(params.getUsername(), params.getTransport().getRemoteHost());
}
@Override
public SSHPacket buildReq()
throws UserAuthException {
return super.buildReq() // the generic stuff
.putString("") // lang-tag
.putString(getCommaSeparatedSubmethodList());
}
private String getCommaSeparatedSubmethodList() {
StringBuilder sb = new StringBuilder();
for (String submethod : provider.getSubmethods()) {
if (sb.length() > 0)
sb.append(",");
sb.append(submethod);
}
return sb.toString();
}
@Override
public void handle(Message cmd, SSHPacket buf)
throws UserAuthException, TransportException {
if (cmd == Message.USERAUTH_60) {
provider.init(resource, buf.readString(), buf.readString());
buf.readString(); // lang-tag
final int numPrompts = buf.readInt();
final List<String> userReplies = new ArrayList<String>(numPrompts);
for (int i = 0; i < numPrompts; i++) {
userReplies.add(provider.getResponse(buf.readString(), buf.readBoolean()));
}
respond(userReplies);
} else
super.handle(cmd, buf);
}
private void respond(List<String> userReplies)
throws TransportException {
final SSHPacket pkt = new SSHPacket(Message.USERAUTH_INFO_RESPONSE)
.putInt(userReplies.size());
for (String response : userReplies) {
pkt.putString(response);
}
params.getTransport().write(pkt);
}
/**
* Returns {@code true} if the associated {@link net.schmizz.sshj.userauth.password.PasswordFinder} tells that we
* should retry with a new password that it will supply.
*/
@Override
public boolean shouldRetry() {
return provider.shouldRetry();
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010 Shikhar Bhushan
*
* Licensed 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.method;
import net.schmizz.sshj.userauth.password.Resource;
import java.util.List;
public interface ChallengeResponseProvider {
List<String> getSubmethods();
void init(Resource resource, String name, String instruction);
String getResponse(String prompt, boolean echo);
boolean shouldRetry();
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2010 Shikhar Bhushan
*
* Licensed 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.method;
import net.schmizz.sshj.userauth.password.PasswordFinder;
import net.schmizz.sshj.userauth.password.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
public class PasswordResponseProvider
implements ChallengeResponseProvider {
private final Logger log = LoggerFactory.getLogger(getClass());
private final PasswordFinder pwdf;
private Resource resource;
private boolean gaveOnce;
public PasswordResponseProvider(PasswordFinder pwdf) {
this.pwdf = pwdf;
}
@Override
public List<String> getSubmethods() {
return Collections.emptyList();
}
@Override
public void init(Resource resource, String name, String instruction) {
this.resource = resource;
log.debug("name=`{}`; instruction=`{}`", name, instruction);
}
@Override
public String getResponse(String prompt, boolean echo) {
if (!gaveOnce && !echo && prompt.toLowerCase().contains("password")) {
gaveOnce = true;
log.debug("prompt = `{}`", prompt);
return new String(pwdf.reqPassword(resource));
}
return "";
}
@Override
public boolean shouldRetry() {
return pwdf.shouldRetry(resource);
}
}