UserAuthKeyboardInteractive.java

Go to the documentation of this file.
00001 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
00002 /*
00003 Copyright (c) 2002-2011 ymnk, JCraft,Inc. All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008   1. Redistributions of source code must retain the above copyright notice,
00009      this list of conditions and the following disclaimer.
00010 
00011   2. Redistributions in binary form must reproduce the above copyright 
00012      notice, this list of conditions and the following disclaimer in 
00013      the documentation and/or other materials provided with the distribution.
00014 
00015   3. The names of the authors may not be used to endorse or promote products
00016      derived from this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00020 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
00021 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
00022 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00025 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00027 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 */
00029 
00030 package com.jcraft.jsch;
00031 
00032 class UserAuthKeyboardInteractive extends UserAuth{
00033   public boolean start(Session session) throws Exception{
00034     super.start(session);
00035 
00036     if(userinfo!=null && !(userinfo instanceof UIKeyboardInteractive)){
00037       return false;
00038     }
00039 
00040     String dest=username+"@"+session.host;
00041     if(session.port!=22){
00042       dest+=(":"+session.port);
00043     }
00044     byte[] password=session.password;
00045 
00046     boolean cancel=false;
00047 
00048     byte[] _username=null;
00049     _username=Util.str2byte(username);
00050 
00051     while(true){
00052       // send
00053       // byte      SSH_MSG_USERAUTH_REQUEST(50)
00054       // string    user name (ISO-10646 UTF-8, as defined in [RFC-2279])
00055       // string    service name (US-ASCII) "ssh-userauth" ? "ssh-connection"
00056       // string    "keyboard-interactive" (US-ASCII)
00057       // string    language tag (as defined in [RFC-3066])
00058       // string    submethods (ISO-10646 UTF-8)
00059       packet.reset();
00060       buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);
00061       buf.putString(_username);
00062       buf.putString(Util.str2byte("ssh-connection"));
00063       //buf.putString("ssh-userauth".getBytes());
00064       buf.putString(Util.str2byte("keyboard-interactive"));
00065       buf.putString(Util.empty);
00066       buf.putString(Util.empty);
00067       session.write(packet);
00068 
00069       boolean firsttime=true;
00070       loop:
00071       while(true){
00072         buf=session.read(buf);
00073         int command=buf.getCommand()&0xff;
00074 
00075     if(command==SSH_MSG_USERAUTH_SUCCESS){
00076       return true;
00077     }
00078     if(command==SSH_MSG_USERAUTH_BANNER){
00079       buf.getInt(); buf.getByte(); buf.getByte();
00080       byte[] _message=buf.getString();
00081       byte[] lang=buf.getString();
00082       String message=Util.byte2str(_message);
00083       if(userinfo!=null){
00084         userinfo.showMessage(message);
00085       }
00086       continue loop;
00087     }
00088     if(command==SSH_MSG_USERAUTH_FAILURE){
00089       buf.getInt(); buf.getByte(); buf.getByte(); 
00090       byte[] foo=buf.getString();
00091       int partial_success=buf.getByte();
00092 //    System.err.println(new String(foo)+
00093 //               " partial_success:"+(partial_success!=0));
00094 
00095       if(partial_success!=0){
00096         throw new JSchPartialAuthException(Util.byte2str(foo));
00097       }
00098 
00099       if(firsttime){
00100         return false;
00101         //throw new JSchException("USERAUTH KI is not supported");
00102         //cancel=true;  // ??
00103       }
00104       break;
00105     }
00106     if(command==SSH_MSG_USERAUTH_INFO_REQUEST){
00107       firsttime=false;
00108       buf.getInt(); buf.getByte(); buf.getByte();
00109       String name=Util.byte2str(buf.getString());
00110       String instruction=Util.byte2str(buf.getString());
00111       String languate_tag=Util.byte2str(buf.getString());
00112       int num=buf.getInt();
00113       String[] prompt=new String[num];
00114       boolean[] echo=new boolean[num];
00115       for(int i=0; i<num; i++){
00116         prompt[i]=Util.byte2str(buf.getString());
00117         echo[i]=(buf.getByte()!=0);
00118       }
00119 
00120       byte[][] response=null;
00121 
00122           if(password!=null && 
00123              prompt.length==1 &&
00124              !echo[0] &&
00125              prompt[0].toLowerCase().startsWith("password:")){
00126             response=new byte[1][];
00127             response[0]=password;
00128             password=null;
00129           }
00130           else if(num>0
00131          ||(name.length()>0 || instruction.length()>0)
00132          ){
00133         if(userinfo!=null){
00134               UIKeyboardInteractive kbi=(UIKeyboardInteractive)userinfo;
00135               String[] _response=kbi.promptKeyboardInteractive(dest,
00136                                                                name,
00137                                                                instruction,
00138                                                                prompt,
00139                                                                echo);
00140               if(_response!=null){
00141                 response=new byte[_response.length][];
00142                 for(int i=0; i<_response.length; i++){
00143                   response[i]=Util.str2byte(_response[i]);
00144                 }
00145               }
00146         }
00147       }
00148 
00149       // byte      SSH_MSG_USERAUTH_INFO_RESPONSE(61)
00150       // int       num-responses
00151       // string    response[1] (ISO-10646 UTF-8)
00152       // ...
00153       // string    response[num-responses] (ISO-10646 UTF-8)
00154       packet.reset();
00155       buf.putByte((byte)SSH_MSG_USERAUTH_INFO_RESPONSE);
00156       if(num>0 &&
00157          (response==null ||  // cancel
00158           num!=response.length)){
00159 
00160             if(response==null){  
00161               // working around the bug in OpenSSH ;-<
00162               buf.putInt(num);
00163               for(int i=0; i<num; i++){
00164                 buf.putString(Util.empty);
00165               }
00166             }
00167             else{
00168               buf.putInt(0);
00169             }
00170 
00171         if(response==null)
00172           cancel=true;
00173       }
00174       else{
00175         buf.putInt(num);
00176         for(int i=0; i<num; i++){
00177           buf.putString(response[i]);
00178         }
00179       }
00180       session.write(packet);
00181           /*
00182       if(cancel)
00183         break;
00184           */
00185       continue loop;
00186     }
00187     //throw new JSchException("USERAUTH fail ("+command+")");
00188     return false;
00189       }
00190       if(cancel){
00191     throw new JSchAuthCancelException("keyboard-interactive");
00192     //break;
00193       }
00194     }
00195     //return false;
00196   }
00197 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1