Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File is getting corrupted when Chunk Mode file transfer interrupted #315

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions src/main/java/com/jcraft/jsch/ChannelSftp.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Hashtable;
import java.util.Vector;



public class ChannelSftp extends ChannelSession {

static private final int LOCAL_MAXIMUM_PACKET_SIZE = 32 * 1024;
Expand Down Expand Up @@ -158,6 +160,7 @@ public class ChannelSftp extends ChannelSession {
private boolean fEncoding_is_utf8 = true;

private RequestQueue rq = new RequestQueue(16);
private Long chunkStart = null;

/**
* Specify how many requests may be sent at any one time. Increasing this value may slightly
Expand Down Expand Up @@ -516,9 +519,10 @@ public void _put(InputStream src, String dst, SftpProgressMonitor monitor, int m
// System.err.println(eee);
}
}
if (mode == RESUME && skip > 0) {
long skipped = src.skip(skip);
if (skipped < skip) {
if (mode == RESUME && skip > 0) {
long srcSkip = chunkStart != null ? skip - chunkStart : skip;
long skipped = src.skip(srcSkip);
if (skipped < srcSkip) {
throw new SftpException(SSH_FX_FAILURE, "failed to resume for " + dst);
}
}
Expand Down Expand Up @@ -643,6 +647,32 @@ public void _put(InputStream src, String dst, SftpProgressMonitor monitor, int m
throw (SftpException) e;
throw new SftpException(SSH_FX_FAILURE, e.toString(), e);
}

public boolean checkChunkFailed(String dst, Long startChunk)throws SftpException{
try{
((MyPipedInputStream)io_in).updateReadSide();

byte[] dstb=Util.str2byte(dst, fEncoding);
long skip=0;
try{
SftpATTRS attr=_stat(dstb);
skip=attr.getSize();
}
catch(Exception eee){
//System.err.println(eee);
}

if(skip>0){
if(skip == startChunk)
return false;
else return true;
}
else return false;
}
catch(Exception e){
throw new SftpException(SSH_FX_FAILURE, "Cannot check-" + e.toString());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We should make sure e isn't already an instance of SftpException first, and if it is, just rethrow it directly.
  2. We should also add the original exception as the cause of the new SftpException.
if (e instanceof SftpException)
  throw (SftpException) e;
throw new SftpException(SSH_FX_FAILURE, e.toString(), e);

}

}

public OutputStream put(String dst) throws SftpException {
Expand Down Expand Up @@ -2952,6 +2982,10 @@ public String realpath(String path) throws SftpException {
throw (SftpException) e;
throw new SftpException(SSH_FX_FAILURE, e.toString(), e);
}
}

public void setChunkStart(String chunkStart) {
this.chunkStart= chunkStart;
}

public static class LsEntry implements Comparable<LsEntry> {
Expand Down
31 changes: 26 additions & 5 deletions src/main/java/com/jcraft/jsch/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ public class Session {

Buffer buf;
Packet packet;

List<String> fingerprintList = new ArrayList<>();

SocketFactory socket_factory = null;

Expand Down Expand Up @@ -883,14 +885,27 @@ private void checkHost(String chost, int port, KeyExchange kex) throws JSchExcep
}
// System.err.println("finger-print: "+key_fprint);
if (userinfo != null) {
boolean foo = userinfo.promptYesNo("The authenticity of host '" + chost
+ "' can't be established.\n" + key_type + " key fingerprint is " + key_fprint + ".\n"
+ "Are you sure you want to continue connecting?");
//Support for Multiple Fingerprints
boolean foo = false;
for(String eachFingerPrint : fingerprintList){
if(key_fprint.equalsIgnoreCase(eachFingerPrint))
{
foo = true;
break;
}
}

if (!foo) {
throw new JSchException("reject HostKey: " + chost);
throw new JSchException(
"Fingerprint invalid. Fingerprint is: "
+ key_fprint);
}
insert = true;
} else {
if(!foo){
throw new JSchException("reject HostKey: "+chost);
}
insert=true;
} else{
if (i == HostKeyRepository.NOT_INCLUDED)
throw new JSchException(
"UnknownHostKey: " + chost + ". " + key_type + " key fingerprint is " + key_fprint);
Expand Down Expand Up @@ -3198,6 +3213,12 @@ private void checkConfig(ConfigRepository.Config config, String key) {
if (value != null)
this.setConfig(key, value);
}

public void addToFingerprintList(String channelFingerprint)
{
String []fingerprints = channelFingerprint.split(",");
this.fingerprintList = new ArrayList<String>(Arrays.asList(fingerprints));
}

/**
* Returns the logger being used by this instance of Session. If no particular logger has been
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ public boolean start(Session session) throws Exception {
byte[][] response = null;

if (password != null && prompt.length == 1 && !echo[0]
&& prompt[0].toLowerCase().indexOf("password:") >= 0) {
&& (prompt[0].toLowerCase().indexOf("password:") >= 0
|| prompt[0].toLowerCase().indexOf("password") >= 0)){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #302 you mention that this change is needed in order to support a server that has a prompt of Enter password:.
However, the string Enter password: already should match prompt[0].toLowerCase().indexOf("password:") >= 0, so I'm not sure I understand the purpose of this change (see below)?

jshell> String foo = "Enter password:";
foo ==> "Enter password:"

jshell> if (foo.toLowerCase().indexOf("password:") >= 0) System.out.println("matches"); else throw new Exception("fail");
matches

jshell> 

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not able to reproduce this issue in my test system so cannot test it. We can leave the changes done in UserAuthKeyboardInteractive.java for now. Please let me know if I need to revert the changes and commit again. Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are not able to reproduce the issue that you believed was fixed by this change, then it should be removed.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The or also overlaps, you could just remove the colon..

response = new byte[1][];
response[0] = password;
password = null;
Expand Down