mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 23:30:55 +03:00
keyboard-interactive auth!
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user