/** @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 Wait for a scp request (file, directory). * * @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending * a file * SSH_SCP_REQUEST_NEWDIR: The other side is sending * a directory * SSH_SCP_REQUEST_ENDDIR: The other side has * finished with the current * directory * SSH_SCP_REQUEST_WARNING: The other side sent us a warning * SSH_SCP_REQUEST_EOF: The other side finished sending us * files and data. * SSH_ERROR: Some error happened * * @see ssh_scp_read() * @see ssh_scp_deny_request() * @see ssh_scp_accept_request() * @see ssh_scp_request_get_warning() */ int ssh_scp_pull_request(ssh_scp scp){ char buffer[MAX_BUF_SIZE] = {0}; char *mode=NULL; char *p,*tmp; uint64_t size; char *name=NULL; int err; if(scp==NULL) return SSH_ERROR; if(scp->state != SSH_SCP_READ_INITED){ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_pull_request called under invalid state"); return SSH_ERROR; } err=ssh_scp_read_string(scp,buffer,sizeof(buffer)); if(err==SSH_ERROR){ if(ssh_channel_is_eof(scp->channel)){ scp->state=SSH_SCP_TERMINATED; return SSH_SCP_REQUEST_EOF; } return err; } p=strchr(buffer,'\n'); if(p!=NULL) *p='\0'; SSH_LOG(SSH_LOG_PROTOCOL,"Received SCP request: '%s'",buffer); switch(buffer[0]){ case 'C': /* File */ case 'D': /* Directory */ p=strchr(buffer,' '); if(p==NULL) goto error; *p='\0'; p++; //mode=strdup(&buffer[1]); scp->request_mode=ssh_scp_integer_mode(&buffer[1]); tmp=p; p=strchr(p,' '); if(p==NULL) goto error; *p=0; size = strtoull(tmp,NULL,10); p++; name=strdup(p); SAFE_FREE(scp->request_name); scp->request_name=name; if(buffer[0]=='C'){ scp->filelen=size; scp->request_type=SSH_SCP_REQUEST_NEWFILE; } else { scp->filelen='0'; scp->request_type=SSH_SCP_REQUEST_NEWDIR; } scp->state=SSH_SCP_READ_REQUESTED; scp->processed = 0; return scp->request_type; break; case 'E': scp->request_type=SSH_SCP_REQUEST_ENDDIR; ssh_channel_write(scp->channel,"",1); return scp->request_type; case 0x1: ssh_set_error(scp->session,SSH_REQUEST_DENIED,"SCP: Warning: %s",&buffer[1]); scp->request_type=SSH_SCP_REQUEST_WARNING; SAFE_FREE(scp->warning); scp->warning=strdup(&buffer[1]); return scp->request_type; case 0x2: ssh_set_error(scp->session,SSH_FATAL,"SCP: Error: %s",&buffer[1]); return SSH_ERROR; case 'T': /* Timestamp */ default: ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: (%d)%s",buffer[0],buffer); return SSH_ERROR; } /* a parsing error occured */ error: SAFE_FREE(name); SAFE_FREE(mode); ssh_set_error(scp->session,SSH_FATAL,"Parsing error while parsing message: %s",buffer); return SSH_ERROR; }