sshclient.java

来自「一个非常好的ssh客户端实现」· Java 代码 · 共 1,227 行 · 第 1/3 页

JAVA
1,227
字号
      outpdu.writeInt(pubKey.getModulus().bitLength());      outpdu.writeBigInteger(pubKey.getPublicExponent());      outpdu.writeBigInteger(pubKey.getModulus());    } else {      outpdu = new SSHPduOutputStream(CMSG_AUTH_RSA, sndCipher, sndComp,				      rand);      outpdu.writeBigInteger(pubKey.getModulus());    }    outpdu.writeTo(sshOut);    SSHPduInputStream inpdu = new SSHPduInputStream(MSG_ANY, rcvCipher, rcvComp);    inpdu.readFrom(sshIn);    if(inpdu.type == SMSG_FAILURE)      throw new  AuthFailException("server refused our key" + (rhosts ? " or rhosts" : ""));    else if(inpdu.type != SMSG_AUTH_RSA_CHALLENGE)      throw new IOException("Protocol error, expected RSA-challenge but got " + inpdu.type);    BigInteger challenge = inpdu.readBigInteger();    // First try with an empty passphrase...    //    RSAPrivateCrtKey privKey = keyFile.getPrivate("");    if(privKey == null)      privKey = keyFile.getPrivate(authenticator.getIdentityPassword(user));    else if(interactor != null)	interactor.report("Authenticated with password-less rsa-key '" + keyFile.getComment() + "'");    if(privKey == null)      throw new AuthFailException("invalid password for key-file '" + keyFile.getComment() + "'");    rsaChallengeResponse(privKey, challenge);  }  private final static int CANNOT_CHOOSE_PIN = 0;  private final static int USER_SELECTABLE   = 1;  private final static int MUST_CHOOSE_PIN   = 2;  void doSDIAuth(String userName) throws IOException {      SSHPduOutputStream outpdu;      String password;      password = authenticator.getChallengeResponse(user, userName +						    "'s SDI token passcode: ");      outpdu = new SSHPduOutputStream(CMSG_AUTH_SDI, sndCipher, sndComp,				      rand);      outpdu.writeString(password);      outpdu.writeTo(sshOut);      SSHPduInputStream inpdu = new SSHPduInputStream(MSG_ANY, rcvCipher, rcvComp);      inpdu.readFrom(sshIn);      switch(inpdu.type) {      case SMSG_SUCCESS:	  interactor.report("SDI authentication accepted.");	  break;      case SMSG_FAILURE:	  throw new AuthFailException("SDI authentication failed.");      case CMSG_ACM_NEXT_CODE_REQUIRED:	  password = interactor.promptPassword("Next token required: ");	  outpdu = new SSHPduOutputStream(CMSG_ACM_NEXT_CODE,					  sndCipher, sndComp, rand);	  outpdu.writeString(password);	  outpdu.writeTo(sshOut);	  if(!isSuccess())	      throw new AuthFailException();	  break;      case CMSG_ACM_NEW_PIN_REQUIRED:	  if(!interactor.askConfirmation("New PIN required, do you want to continue?", false))	      throw new AuthFailException("new PIN not wanted");	  String type       = inpdu.readString();	  String size       = inpdu.readString();	  int    userSelect = inpdu.readInt();	  switch(userSelect) {	  case CANNOT_CHOOSE_PIN:	      break;	  case USER_SELECTABLE:	  case MUST_CHOOSE_PIN:	      String pwdChk;	      do {		  password =		      interactor.promptPassword("Please enter new PIN" +						" containing " + size +						" " + type);		  pwdChk =		      interactor.promptPassword("Please enter new PIN again");	      } while (!password.equals(pwdChk));          outpdu = new SSHPduOutputStream(CMSG_ACM_NEW_PIN, sndCipher, sndComp,					  rand);	  outpdu.writeString(password);	  outpdu.writeTo(sshOut);	  inpdu = new SSHPduInputStream(MSG_ANY, rcvCipher, rcvComp);	  inpdu.readFrom(sshIn);	  if(inpdu.type != CMSG_ACM_NEW_PIN_ACCEPTED) {	      throw new AuthFailException("PIN rejected by server");	  }	  throw new AuthFailException("new PIN accepted, " +				      "wait for the code on your token to change");	  default:	      throw new AuthFailException("invalid response from server");	  }	  break;      case CMSG_ACM_ACCESS_DENIED:	  // Fall through      default:	  throw new AuthFailException();      }  }  void rsaChallengeResponse(RSAPrivateCrtKey privKey, BigInteger challenge)      throws IOException  {    MessageDigest md5;    try {	challenge = RSAAlgorithm.doPrivateCrt(challenge,					      privKey.getPrimeP(),					      privKey.getPrimeQ(),					      privKey.getPrimeExponentP(),					      privKey.getPrimeExponentQ(),					      privKey.getCrtCoefficient());	challenge = RSAAlgorithm.stripPKCS1Pad(challenge, 2);    } catch(Exception e) {	throw new IOException(e.getMessage());    }    byte[] response = challenge.toByteArray();    try {      md5 = MessageDigest.getInstance("MD5");      if(response[0] == 0)	md5.update(response, 1, 32);      else	md5.update(response, 0, 32);      md5.update(sessionId);      response = md5.digest();    } catch(Exception e) {      throw new IOException("MD5 not implemented, can't generate session-id");    }    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_AUTH_RSA_RESPONSE,						       sndCipher, sndComp,						       rand);    outpdu.write(response, 0, response.length);    outpdu.writeTo(sshOut);    if(!isSuccess())      throw new AuthFailException();  }  void initiateSession() throws IOException {    if(user.wantPTY())      requestPTY();    int maxPktSz = user.getMaxPacketSz();    if(maxPktSz > 0)      requestMaxPacketSz(maxPktSz);    if(user.wantX11Forward())      requestX11Forward();    if(activateTunnels)      initiateTunnels();    if(commandLine != null)      requestCommand(commandLine);    else      requestShell();    // !!!    // At this stage we can't send more options/forward-requests    // the server has now entered it's service-loop.  }  void initiatePlugins() {    SSHProtocolPlugin.initiateAll(this);  }  void initiateTunnels() throws IOException {    int i;    for(i = 0; i < localForwards.size(); i++) {      LocalForward fwd = (LocalForward) localForwards.elementAt(i);      requestLocalPortForward(fwd.localHost, fwd.localPort, fwd.remoteHost, fwd.remotePort, fwd.plugin);    }    for(i = 0; i < remoteForwards.size(); i++) {      RemoteForward fwd = (RemoteForward) remoteForwards.elementAt(i);      requestRemotePortForward(fwd.remotePort, fwd.localHost, fwd.localPort, fwd.plugin);    }  }  void requestCompression(int level) throws IOException {      if(level == 0) {	  return;      }      SSHPduOutputStream outpdu =	  new SSHPduOutputStream(CMSG_REQUEST_COMPRESSION, sndCipher, sndComp,				 rand);      outpdu.writeInt(level);      outpdu.writeTo(sshOut);      if(!isSuccess() && interactor != null)	  interactor.report("Error requesting compression level: " + level);      sndComp = SSHCompressor.getInstance("zlib", SSHCompressor.COMPRESS_MODE,					  level);      rcvComp = SSHCompressor.getInstance("zlib", SSHCompressor.UNCOMPRESS_MODE,					  level);  }  void requestMaxPacketSz(int sz) throws IOException {    SSHPduOutputStream outpdu = new SSHPduOutputStream(CMSG_MAX_PACKET_SIZE,						       sndCipher, sndComp,						       rand);    outpdu.writeInt(sz);    outpdu.writeTo(sshOut);    if(!isSuccess() && interactor != null)	interactor.report("Error requesting max packet size: " + sz);  }  void requestX11Forward() throws IOException {    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_X11_REQUEST_FORWARDING, sndCipher, sndComp,			       rand);    // !!!    outpdu.writeString("MIT-MAGIC-COOKIE-1");    outpdu.writeString("112233445566778899aabbccddeeff00");    outpdu.writeInt(0);    // !!!    outpdu.writeTo(sshOut);    if(!isSuccess() && interactor != null)	interactor.report("Error requesting X11 forward");  }  void requestPTY() throws IOException {    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_REQUEST_PTY, sndCipher, sndComp, rand);    Terminal myTerminal = null;    if(console != null)      myTerminal = console.getTerminal();    if(myTerminal != null) {      outpdu.writeString(myTerminal.terminalType());      outpdu.writeInt(myTerminal.rows());      outpdu.writeInt(myTerminal.cols());      outpdu.writeInt(myTerminal.vpixels());      outpdu.writeInt(myTerminal.hpixels());    } else {      outpdu.writeString("");      outpdu.writeInt(0);      outpdu.writeInt(0);      outpdu.writeInt(0);      outpdu.writeInt(0);    }    outpdu.writeByte((byte)TTY_OP_END);    outpdu.writeTo(sshOut);    if(!isSuccess() && interactor != null)	interactor.report("Error requesting PTY");  }  void requestLocalPortForward(String localHost, int localPort, String remoteHost, int remotePort, String plugin)      throws IOException {    controller.newListenChannel(localHost, localPort, remoteHost, remotePort, plugin);  }  void requestRemotePortForward(int remotePort, String localHost, int localPort, String plugin)    throws IOException {    try {	SSHProtocolPlugin.getPlugin(plugin).remoteListener(remotePort, localHost, localPort,							   controller);    } catch (NoClassDefFoundError e) {	throw new IOException("Plugins not available");    }    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_PORT_FORWARD_REQUEST, sndCipher, sndComp,			       rand);    outpdu.writeInt(remotePort);    outpdu.writeString(localHost);    outpdu.writeInt(localPort);    outpdu.writeTo(sshOut);    if(!isSuccess() && interactor != null) {	interactor.report("Error requesting remote port forward: " + plugin +			  "/" + remotePort + ":" + localHost + ":" + localPort);    }  }  void requestCommand(String command) throws IOException {    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_EXEC_CMD, sndCipher, sndComp, rand);    outpdu.writeString(command);    outpdu.writeTo(sshOut);  }  void requestShell() throws IOException {    SSHPduOutputStream outpdu =	new SSHPduOutputStream(CMSG_EXEC_SHELL, sndCipher, sndComp, rand);    outpdu.writeTo(sshOut);  }  boolean isSuccess() throws IOException {    boolean success = false;    SSHPduInputStream inpdu = null;    inpdu = new SSHPduInputStream(MSG_ANY, rcvCipher, rcvComp);    inpdu.readFrom(sshIn);    if(inpdu.type == SMSG_SUCCESS)      success = true;    else if(inpdu.type == SMSG_FAILURE)      success = false;    else if(inpdu.type == MSG_DISCONNECT)      throw new IOException("Server disconnected: " + inpdu.readString());    else       throw new IOException("Protocol error: got " + inpdu.type + 			    " when expecting success/failure");    return success;  }  void setInteractive() {    try {      sshSocket.setTcpNoDelay(true);    } catch (SocketException e) {	if(interactor != null)	    interactor.report("Error setting interactive mode: " + e.getMessage());    }  }  void setAliveInterval(int i) {      if(i == 0) {	  if(keepAliveThread != null && keepAliveThread.isAlive())	      keepAliveThread.stop();	  keepAliveThread = null;      } else {	  if(keepAliveThread != null) {	      keepAliveThread.setInterval(i);	  } else {	      keepAliveThread = new KeepAliveThread(i);	      keepAliveThread.setDaemon(true);	      keepAliveThread.start();	  }      }  }  public boolean isOpened() {      return isOpened;  }  public boolean isConnected() {      return isConnected;  }  void stdinWriteChar(char c) throws IOException {    stdinWriteString(String.valueOf(c));  }  void stdinWriteString(String str) throws IOException {    stdinWriteString(str.getBytes(), 0, str.length());  }  void stdinWriteString(byte[] str) throws IOException {    stdinWriteString(str, 0, str.length);  }  void stdinWriteString(byte[] str, int off, int len) throws IOException {    SSHPduOutputStream stdinPdu;    if(isOpened && controller != null) {      stdinPdu = new SSHPduOutputStream(SSH.CMSG_STDIN_DATA, sndCipher, sndComp,					rand);      stdinPdu.writeInt(len);      stdinPdu.write(str, off, len);      controller.transmit(stdinPdu);    }  }  void signalWindowChanged(int rows, int cols, int vpixels, int hpixels) {    if(isOpened && controller != null) {      try {	SSHPduOutputStream pdu;	pdu = new SSHPduOutputStream(SSH.CMSG_WINDOW_SIZE, sndCipher, sndComp,				     rand);	pdu.writeInt(rows);	pdu.writeInt(cols);	pdu.writeInt(vpixels);	pdu.writeInt(hpixels);	controller.transmit(pdu);      } catch (Exception ex) {	  if(interactor != null)	      interactor.alert("Error when sending sigWinch: " + ex.toString());      }    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?