mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 10:40:27 +09:00
Add better error detection + EOF request
This commit is contained in:
@@ -474,7 +474,9 @@ enum ssh_scp_request_types {
|
|||||||
/** A new directory is going to be pulled */
|
/** A new directory is going to be pulled */
|
||||||
SSH_SCP_REQUEST_NEWDIR=1,
|
SSH_SCP_REQUEST_NEWDIR=1,
|
||||||
/** A new file is going to be pulled */
|
/** A new file is going to be pulled */
|
||||||
SSH_SCP_REQUEST_NEWFILE
|
SSH_SCP_REQUEST_NEWFILE,
|
||||||
|
/** End of requests */
|
||||||
|
SSH_SCP_REQUEST_EOF
|
||||||
};
|
};
|
||||||
|
|
||||||
LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location);
|
LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location);
|
||||||
|
|||||||
@@ -358,7 +358,8 @@ enum ssh_scp_states {
|
|||||||
SSH_SCP_READ_INITED, //Gave our intention to read
|
SSH_SCP_READ_INITED, //Gave our intention to read
|
||||||
SSH_SCP_READ_REQUESTED, //We got a read request
|
SSH_SCP_READ_REQUESTED, //We got a read request
|
||||||
SSH_SCP_READ_READING, //File is opened and reading
|
SSH_SCP_READ_READING, //File is opened and reading
|
||||||
SSH_SCP_ERROR //Something bad happened
|
SSH_SCP_ERROR, //Something bad happened
|
||||||
|
SSH_SCP_TERMINATED //Transfer finished
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_scp_struct {
|
struct ssh_scp_struct {
|
||||||
@@ -866,6 +867,7 @@ int ssh_execute_message_callbacks(SSH_SESSION *session);
|
|||||||
int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len);
|
int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len);
|
||||||
int ssh_scp_integer_mode(const char *mode);
|
int ssh_scp_integer_mode(const char *mode);
|
||||||
char *ssh_scp_string_mode(int mode);
|
char *ssh_scp_string_mode(int mode);
|
||||||
|
int ssh_scp_response(ssh_scp scp, char **response);
|
||||||
|
|
||||||
/* log.c */
|
/* log.c */
|
||||||
|
|
||||||
|
|||||||
69
libssh/scp.c
69
libssh/scp.c
@@ -234,6 +234,48 @@ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief waits for a response of the scp server
|
||||||
|
* @internal
|
||||||
|
* @param response pointer where the response message must be
|
||||||
|
* copied if any. This pointer must then be free'd.
|
||||||
|
* @returns the return code.
|
||||||
|
* @returns SSH_ERROR a error occured
|
||||||
|
*/
|
||||||
|
int ssh_scp_response(ssh_scp scp, char **response){
|
||||||
|
unsigned char code;
|
||||||
|
int r;
|
||||||
|
char msg[128];
|
||||||
|
r=channel_read(scp->channel,&code,1,0);
|
||||||
|
if(r == SSH_ERROR)
|
||||||
|
return SSH_ERROR;
|
||||||
|
if(code == 0)
|
||||||
|
return 0;
|
||||||
|
if(code > 2){
|
||||||
|
ssh_set_error(scp->session,SSH_FATAL, "SCP: invalid status code %ud received", code);
|
||||||
|
scp->state=SSH_SCP_ERROR;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
r=ssh_scp_read_string(scp,msg,sizeof(msg));
|
||||||
|
if(r==SSH_ERROR)
|
||||||
|
return r;
|
||||||
|
/* Warning */
|
||||||
|
if(code == 1){
|
||||||
|
ssh_set_error(scp->session,SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg);
|
||||||
|
ssh_log(scp->session,SSH_LOG_RARE,"SCP: Warning: status code 1 received: %s", msg);
|
||||||
|
if(response)
|
||||||
|
*response=strdup(msg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(code == 2){
|
||||||
|
ssh_set_error(scp->session,SSH_FATAL, "SCP: Error: status code 2 received: %s", msg);
|
||||||
|
if(response)
|
||||||
|
*response=strdup(msg);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
/* Not reached */
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Write into a remote scp file
|
/** @brief Write into a remote scp file
|
||||||
* @param buffer the buffer to write
|
* @param buffer the buffer to write
|
||||||
* @param len the number of bytes to write
|
* @param len the number of bytes to write
|
||||||
@@ -330,8 +372,13 @@ int ssh_scp_pull_request(ssh_scp scp){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
err=ssh_scp_read_string(scp,buffer,sizeof(buffer));
|
err=ssh_scp_read_string(scp,buffer,sizeof(buffer));
|
||||||
if(err==SSH_ERROR)
|
if(err==SSH_ERROR){
|
||||||
|
if(channel_is_eof(scp->channel)){
|
||||||
|
scp->state=SSH_SCP_TERMINATED;
|
||||||
|
return SSH_SCP_REQUEST_EOF;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
p=strchr(buffer,'\n');
|
p=strchr(buffer,'\n');
|
||||||
if(p!=NULL)
|
if(p!=NULL)
|
||||||
*p='\0';
|
*p='\0';
|
||||||
@@ -373,13 +420,13 @@ int ssh_scp_pull_request(ssh_scp scp){
|
|||||||
/* Timestamp */
|
/* Timestamp */
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: %s",&buffer[1]);
|
ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: Warning: %s",&buffer[1]);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
ssh_set_error(scp->session,SSH_FATAL,"SCP: %s",&buffer[1]);
|
ssh_set_error(scp->session,SSH_FATAL,"SCP: Error: %s",&buffer[1]);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
default:
|
default:
|
||||||
ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: %s",buffer);
|
ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: (%d)%s",buffer[0],buffer);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +496,7 @@ int ssh_scp_accept_request(ssh_scp scp){
|
|||||||
*/
|
*/
|
||||||
int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
|
int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
|
||||||
int r;
|
int r;
|
||||||
|
int code;
|
||||||
if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){
|
if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){
|
||||||
r=ssh_scp_accept_request(scp);
|
r=ssh_scp_accept_request(scp);
|
||||||
if(r==SSH_ERROR)
|
if(r==SSH_ERROR)
|
||||||
@@ -472,7 +520,18 @@ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
|
|||||||
/* Check if we arrived at end of file */
|
/* Check if we arrived at end of file */
|
||||||
if(scp->processed == scp->filelen) {
|
if(scp->processed == scp->filelen) {
|
||||||
scp->processed=scp->filelen=0;
|
scp->processed=scp->filelen=0;
|
||||||
scp->state=SSH_SCP_READ_INITED;
|
channel_write(scp->channel,"",1);
|
||||||
|
code=ssh_scp_response(scp,NULL);
|
||||||
|
if(code == 0){
|
||||||
|
scp->state=SSH_SCP_READ_INITED;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if(code==1){
|
||||||
|
scp->state=SSH_SCP_READ_INITED;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
scp->state=SSH_SCP_ERROR;
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user