/* * Copyright (C)2009 - SSHJ Contributors * * 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.Buffer; import net.schmizz.sshj.common.Message; import net.schmizz.sshj.common.SSHPacket; import net.schmizz.sshj.transport.TransportException; import net.schmizz.sshj.userauth.UserAuthException; /** Implements the {@code keyboard-interactive} authentication method. */ public class AuthKeyboardInteractive extends AbstractAuthMethod { private final ChallengeResponseProvider provider; public AuthKeyboardInteractive(ChallengeResponseProvider provider) { super("keyboard-interactive"); this.provider = provider; } @Override public SSHPacket buildReq() throws UserAuthException { return super.buildReq() // the generic stuff .putString("") // lang-tag .putString(buildCommaSeparatedSubmethodList()); } private String buildCommaSeparatedSubmethodList() { StringBuilder sb = new StringBuilder(); for (String submethod : provider.getSubmethods()) { if (sb.length() > 0) sb.append(","); sb.append(submethod); } return sb.toString(); } private static class CharArrWrap { private final char[] arr; private CharArrWrap(char[] arr) { this.arr = arr; } } @Override public void handle(Message cmd, SSHPacket buf) throws UserAuthException, TransportException { if (cmd != Message.USERAUTH_60) { super.handle(cmd, buf); } else { final CharArrWrap[] userReplies; try { provider.init(makeAccountResource(), buf.readString(), buf.readString()); buf.readString(); // lang-tag final int numPrompts = buf.readUInt32AsInt(); userReplies = new CharArrWrap[numPrompts]; for (int i = 0; i < numPrompts; i++) { final String prompt = buf.readString(); final boolean echo = buf.readBoolean(); log.debug("Requesting response for challenge `{}`; echo={}", prompt, echo); userReplies[i] = new CharArrWrap(provider.getResponse(prompt, echo)); } } catch (Buffer.BufferException be) { throw new UserAuthException(be); } respond(userReplies); } } private void respond(CharArrWrap[] userReplies) throws TransportException { final SSHPacket pkt = new SSHPacket(Message.USERAUTH_INFO_RESPONSE).putUInt32(userReplies.length); for (final CharArrWrap response : userReplies) pkt.putSensitiveString(response.arr); params.getTransport().write(pkt); } @Override public boolean shouldRetry() { return provider.shouldRetry(); } }