uint32_t sftp_parse_handle(struct sftpjob *job, struct handleid *id) { uint32_t len, rc; if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK || len != 8 || (rc = sftp_parse_uint32(job, &id->id)) != SSH_FX_OK || (rc = sftp_parse_uint32(job, &id->tag) != SSH_FX_OK)) return rc; return SSH_FX_OK; }
void queue_serializable_job(struct sftpjob *job) { uint8_t type; uint32_t id; uint64_t offset, len64; uint32_t len; struct handleid hid; unsigned handleflags; struct sqnode *q; job->ptr = job->data; job->left = job->len; if(!sftp_parse_uint8(job, &type) && (type == SSH_FXP_READ || type == SSH_FXP_WRITE) && sftp_parse_uint32(job, &id) == SSH_FX_OK && sftp_parse_handle(job, &hid) == SSH_FX_OK && sftp_parse_uint64(job, &offset) == SSH_FX_OK && sftp_parse_uint32(job, &len) == SSH_FX_OK) { /* This is a well-formed read or write operation */ len64 = len; handleflags = sftp_handle_flags(&hid); } else { /* Anything else has dummy values */ memset(&hid, 0, sizeof hid); offset = 0; len64 = ~(uint64_t)0; handleflags = 0; } ferrcheck(pthread_mutex_lock(&sq_mutex)); q = xmalloc(sizeof *q); q->older = newest; q->job = job; q->type = type; q->hid = hid; q->handleflags = handleflags; q->offset = offset; q->len = len64; newest = q; ferrcheck(pthread_mutex_unlock(&sq_mutex)); }
/* Command code for the various _*STAT calls. rc is the return value * from *stat() and SB is the buffer. */ static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc, const struct stat *sb, const char *path) { struct sftpattr attrs; uint32_t flags; if(!rc) { pcheck(sftp_parse_uint32(job, &flags)); sftp_stat_to_attrs(job->a, sb, &attrs, flags, path); sftp_send_begin(job->worker); sftp_send_uint8(job->worker, SSH_FXP_ATTRS); sftp_send_uint32(job->worker, job->id); protocol->sendattrs(job, &attrs); sftp_send_end(job->worker); return HANDLER_RESPONDED; } else return HANDLER_ERRNO; }
uint32_t sftp_parse_string(struct sftpjob *job, char **strp, size_t *lenp) { uint32_t len, rc; char *str; if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK) return rc; if(len == 0xFFFFFFFF) return SSH_FX_BAD_MESSAGE; /* overflow */ if(job->left < len) return SSH_FX_BAD_MESSAGE; /* not enough bytes to satisfy */ if(lenp) *lenp = len; if(strp) { str = sftp_alloc(job->a, len + 1); /* 0-fills */ memcpy(str, job->ptr, len); *strp = str; } job->ptr += len; job->left -= len; return SSH_FX_OK; }
uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) { uint32_t n, rc; memset(attrs, 0, sizeof *attrs); if((rc = sftp_parse_uint32(job, &attrs->valid)) != SSH_FX_OK) return rc; if((attrs->valid & protocol->attrmask) != attrs->valid) { D(("received attrs %#x but protocol %d only supports %#x", attrs->valid, protocol->version, protocol->attrmask)); attrs->valid = 0; return SSH_FX_BAD_MESSAGE; } if((rc = sftp_parse_uint8(job, &attrs->type)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_SIZE) if((rc = sftp_parse_uint64(job, &attrs->size)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_OWNERGROUP) { if((rc = sftp_parse_path(job, &attrs->owner)) != SSH_FX_OK) return rc; if((rc = sftp_parse_path(job, &attrs->group)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_PERMISSIONS) { if((rc = sftp_parse_uint32(job, &attrs->permissions)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_ACCESSTIME) { if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->atime.seconds)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) if((rc = sftp_parse_uint32(job, &attrs->atime.nanoseconds)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_CREATETIME) { if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->createtime.seconds)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) if((rc = sftp_parse_uint32(job, &attrs->createtime.nanoseconds)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_MODIFYTIME) { if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->mtime.seconds)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) if((rc = sftp_parse_uint32(job, &attrs->mtime.nanoseconds)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_CTIME) { if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->ctime.seconds)) != SSH_FX_OK) return rc; if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) if((rc = sftp_parse_uint32(job, &attrs->ctime.nanoseconds)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_ACL) { if((rc = sftp_parse_string(job, &attrs->acl, 0)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_BITS) { if((rc = sftp_parse_uint32(job, &attrs->attrib_bits)) != SSH_FX_OK) return rc; if(protocol->version >= 6) { if((rc = sftp_parse_uint32(job, &attrs->attrib_bits_valid)) != SSH_FX_OK) return rc; } else attrs->attrib_bits_valid = 0x7ff; /* -05 s5.8 */ } if(attrs->valid & SSH_FILEXFER_ATTR_TEXT_HINT) { if((rc = sftp_parse_uint8(job, &attrs->text_hint)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_MIME_TYPE) { if((rc = sftp_parse_string(job, &attrs->mime_type, 0)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_LINK_COUNT) { if((rc = sftp_parse_uint32(job, &attrs->link_count)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) { if((rc = sftp_parse_string(job, &attrs->mime_type, 0)) != SSH_FX_OK) return rc; } if(attrs->valid & SSH_FILEXFER_ATTR_EXTENDED) { if((rc = sftp_parse_uint32(job, &n)) != SSH_FX_OK) return rc; while(n-- > 0) { if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK) return rc; if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK) return rc; } } return SSH_FX_OK; }