Add better error detection + EOF request

This commit is contained in:
Aris Adamantiadis
2009-09-06 14:26:33 +03:00
parent 480dfd9050
commit 7ff80a2666
3 changed files with 70 additions and 7 deletions

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;
channel_write(scp->channel,"",1);
code=ssh_scp_response(scp,NULL);
if(code == 0){
scp->state=SSH_SCP_READ_INITED; 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;
} }