📄 trans2.c
字号:
} /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_fileinfo_level)level; if (st->generic.level >= RAW_FILEINFO_GENERIC) { return NT_STATUS_INVALID_LEVEL; } if (st->generic.level == RAW_FILEINFO_EA_LIST) { TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req, &st->ea_list.in.num_names, &st->ea_list.in.ea_names)); } op->op_info = st; op->send_fn = trans2_fileinfo_send; return ntvfs_qpathinfo(req->ntvfs, st);}/* trans2 qpathinfo implementation*/static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op){ struct smb_trans2 *trans = op->trans; union smb_fileinfo *st; uint16_t level; struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { return NT_STATUS_FOOBAR; } st = talloc(op, union smb_fileinfo); NT_STATUS_HAVE_NO_MEMORY(st); h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_fileinfo_level)level; if (st->generic.level >= RAW_FILEINFO_GENERIC) { return NT_STATUS_INVALID_LEVEL; } if (st->generic.level == RAW_FILEINFO_EA_LIST) { TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req, &st->ea_list.in.num_names, &st->ea_list.in.ea_names)); } op->op_info = st; op->send_fn = trans2_fileinfo_send; SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, st);}/* parse a trans2 setfileinfo/setpathinfo data blob*/static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req, union smb_setfileinfo *st, const DATA_BLOB *blob){ enum smb_setfileinfo_level passthru_level; switch (st->generic.level) { case RAW_SFILEINFO_GENERIC: case RAW_SFILEINFO_SETATTR: case RAW_SFILEINFO_SETATTRE: case RAW_SFILEINFO_SEC_DESC: /* handled elsewhere */ return NT_STATUS_INVALID_LEVEL; case RAW_SFILEINFO_STANDARD: CHECK_MIN_BLOB_SIZE(blob, 12); st->standard.in.create_time = srv_pull_dos_date2(req->smb_conn, blob->data + 0); st->standard.in.access_time = srv_pull_dos_date2(req->smb_conn, blob->data + 4); st->standard.in.write_time = srv_pull_dos_date2(req->smb_conn, blob->data + 8); return NT_STATUS_OK; case RAW_SFILEINFO_EA_SET: return ea_pull_list(blob, req, &st->ea_set.in.num_eas, &st->ea_set.in.eas); case SMB_SFILEINFO_BASIC_INFO: case SMB_SFILEINFO_BASIC_INFORMATION: passthru_level = SMB_SFILEINFO_BASIC_INFORMATION; break; case SMB_SFILEINFO_DISPOSITION_INFO: case SMB_SFILEINFO_DISPOSITION_INFORMATION: passthru_level = SMB_SFILEINFO_DISPOSITION_INFORMATION; break; case SMB_SFILEINFO_ALLOCATION_INFO: case SMB_SFILEINFO_ALLOCATION_INFORMATION: passthru_level = SMB_SFILEINFO_ALLOCATION_INFORMATION; break; case RAW_SFILEINFO_END_OF_FILE_INFO: case RAW_SFILEINFO_END_OF_FILE_INFORMATION: passthru_level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; break; case RAW_SFILEINFO_RENAME_INFORMATION: case RAW_SFILEINFO_POSITION_INFORMATION: case RAW_SFILEINFO_MODE_INFORMATION: passthru_level = st->generic.level; break; case RAW_SFILEINFO_UNIX_BASIC: case RAW_SFILEINFO_UNIX_LINK: case RAW_SFILEINFO_UNIX_HLINK: case RAW_SFILEINFO_1023: case RAW_SFILEINFO_1025: case RAW_SFILEINFO_1029: case RAW_SFILEINFO_1032: case RAW_SFILEINFO_1039: case RAW_SFILEINFO_1040: return NT_STATUS_INVALID_LEVEL; default: /* we need a default here to cope with invalid values on the wire */ return NT_STATUS_INVALID_LEVEL; } return smbsrv_pull_passthru_sfileinfo(st, passthru_level, st, blob, SMBSRV_REQ_DEFAULT_STR_FLAGS(req), &req->in.bufinfo);}/* trans2 setfileinfo implementation*/static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *op){ struct smb_trans2 *trans = op->trans; union smb_setfileinfo *st; uint16_t level; struct ntvfs_handle *h; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { return NT_STATUS_FOOBAR; } st = talloc(op, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(st); h = smbsrv_pull_fnum(req, trans->in.params.data, 0); level = SVAL(trans->in.params.data, 2); st->generic.in.file.ntvfs = h; /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_setfileinfo_level)level; if (st->generic.level >= RAW_SFILEINFO_GENERIC) { return NT_STATUS_INVALID_LEVEL; } TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data)); op->op_info = st; op->send_fn = trans2_simple_send; SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, st);}/* trans2 setpathinfo implementation*/static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *op){ struct smb_trans2 *trans = op->trans; union smb_setfileinfo *st; uint16_t level; /* make sure we got enough parameters */ if (trans->in.params.length < 4) { return NT_STATUS_FOOBAR; } st = talloc(op, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(st); level = SVAL(trans->in.params.data, 0); smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0); if (st->generic.in.file.path == NULL) { return NT_STATUS_FOOBAR; } /* work out the backend level - we make it 1-1 in the header */ st->generic.level = (enum smb_setfileinfo_level)level; if (st->generic.level >= RAW_SFILEINFO_GENERIC) { return NT_STATUS_INVALID_LEVEL; } TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data)); op->op_info = st; op->send_fn = trans2_simple_send; return ntvfs_setpathinfo(req->ntvfs, st);}/* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */struct find_state { struct trans_op *op; void *search; enum smb_search_data_level data_level; uint16_t last_entry_offset; uint16_t flags;};/* fill a single entry in a trans2 find reply */static NTSTATUS find_fill_info(struct find_state *state, const union smb_search_data *file){ struct smbsrv_request *req = state->op->req; struct smb_trans2 *trans = state->op->trans; uint8_t *data; uint_t ofs = trans->out.data.length; uint32_t ea_size; switch (state->data_level) { case RAW_SEARCH_DATA_GENERIC: case RAW_SEARCH_DATA_SEARCH: /* handled elsewhere */ return NT_STATUS_INVALID_LEVEL; case RAW_SEARCH_DATA_STANDARD: if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27)); SIVAL(trans->out.data.data, ofs, file->standard.resume_key); ofs += 4; } else { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 23)); } data = trans->out.data.data + ofs; srv_push_dos_date2(req->smb_conn, data, 0, file->standard.create_time); srv_push_dos_date2(req->smb_conn, data, 4, file->standard.access_time); srv_push_dos_date2(req->smb_conn, data, 8, file->standard.write_time); SIVAL(data, 12, file->standard.size); SIVAL(data, 16, file->standard.alloc_size); SSVAL(data, 20, file->standard.attrib); TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->standard.name.s, ofs + 22, SMBSRV_REQ_DEFAULT_STR_FLAGS(req), STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM)); break; case RAW_SEARCH_DATA_EA_SIZE: if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 31)); SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key); ofs += 4; } else { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27)); } data = trans->out.data.data + ofs; srv_push_dos_date2(req->smb_conn, data, 0, file->ea_size.create_time); srv_push_dos_date2(req->smb_conn, data, 4, file->ea_size.access_time); srv_push_dos_date2(req->smb_conn, data, 8, file->ea_size.write_time); SIVAL(data, 12, file->ea_size.size); SIVAL(data, 16, file->ea_size.alloc_size); SSVAL(data, 20, file->ea_size.attrib); SIVAL(data, 22, file->ea_size.ea_size); TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->ea_size.name.s, ofs + 26, SMBSRV_REQ_DEFAULT_STR_FLAGS(req), STR_LEN8BIT | STR_NOALIGN)); TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1)); break; case RAW_SEARCH_DATA_EA_LIST: ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas); if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27 + ea_size)); SIVAL(trans->out.data.data, ofs, file->ea_list.resume_key); ofs += 4; } else { TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 23 + ea_size)); } data = trans->out.data.data + ofs; srv_push_dos_date2(req->smb_conn, data, 0, file->ea_list.create_time); srv_push_dos_date2(req->smb_conn, data, 4, file->ea_list.access_time); srv_push_dos_date2(req->smb_conn, data, 8, file->ea_list.write_time); SIVAL(data, 12, file->ea_list.size); SIVAL(data, 16, file->ea_list.alloc_size); SSVAL(data, 20, file->ea_list.attrib); ea_put_list(data+22, file->ea_list.eas.num_eas, file->ea_list.eas.eas); TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->ea_list.name.s, ofs + 22 + ea_size, SMBSRV_REQ_DEFAULT_STR_FLAGS(req), STR_LEN8BIT | STR_NOALIGN)); TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1)); break; case RAW_SEARCH_DATA_DIRECTORY_INFO: case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO: case RAW_SEARCH_DATA_NAME_INFO: case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO: case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO: case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO: return smbsrv_push_passthru_search(trans, &trans->out.data, state->data_level, file, SMBSRV_REQ_DEFAULT_STR_FLAGS(req)); case RAW_SEARCH_DATA_UNIX_INFO: return NT_STATUS_INVALID_LEVEL; } return NT_STATUS_OK;}/* callback function for trans2 findfirst/findnext */static bool find_callback(void *private, const union smb_search_data *file){ struct find_state *state = talloc_get_type(private, struct find_state); struct smb_trans2 *trans = state->op->trans; uint_t old_length; old_length = trans->out.data.length; if (!NT_STATUS_IS_OK(find_fill_info(state, file)) || trans->out.data.length > trans->in.max_data) { /* restore the old length and tell the backend to stop */ smbsrv_blob_grow_data(trans, &trans->out.data, old_length); return false; } state->last_entry_offset = old_length; return true;}/* trans2 findfirst send */static NTSTATUS trans2_findfirst_send(struct trans_op *op){ struct smbsrv_request *req = op->req; struct smb_trans2 *trans = op->trans; union smb_search_first *search; struct find_state *state; uint8_t *param; TRANS2_CHECK_ASYNC_STATUS(state, struct find_state); search = talloc_get_type(state->search, union smb_search_first); /* fill in the findfirst reply header */ param = trans->out.params.data; SSVAL(param, VWV(0), search->t2ffirst.out.handle); SSVAL(param, VWV(1), search->t2ffirst.out.count); SSVAL(param, VWV(2), search->t2ffirst.out.end_of_search); SSVAL(param, VWV(3), 0); SSVAL(param, VWV(4), state->last_entry_offset); return NT_STATUS_OK;}/* trans2 findfirst implementation*/static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op){ struct smb_trans2 *trans = op->trans; union smb_search_first *search; uint16_t level; struct find_state *state; /* make sure we got all the parameters */ if (trans->in.params.length < 14) { return NT_STATUS_FOOBAR; } search = talloc(op, union smb_search_first); NT_STATUS_HAVE_NO_MEMORY(search); search->t2ffirst.in.search_attrib = SVAL(trans->in.params.data, 0); search->t2ffirst.in.max_count = SVAL(trans->in.params.data, 2); search->t2ffirst.in.flags = SVAL(trans->in.params.data, 4); level = SVAL(trans->in.params.data, 6); search->t2ffirst.in.storage_type = IVAL(trans->in.params.data, 8); smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0); if (search->t2ffirst.in.pattern == NULL) { return NT_STATUS_FOOBAR; } search->t2ffirst.level = RAW_SEARCH_TRANS2; search->t2ffirst.data_level = (enum smb_search_data_level)level; if (search->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) { return NT_STATUS_INVALID_LEVEL; } if (search->t2ffirst.data_level == RAW_SEARCH_DATA_EA_LIST) { TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req, &search->t2ffirst.in.num_names, &search->t2ffirst.in.ea_names)); } /* setup the private state structure that the backend will give us in the callback */ state = talloc(op, struct find_state); NT_STATUS_HAVE_NO_MEMORY(state); state->op = op; state->search = search; state->data_level = search->t2ffirst.data_level; state->last_entry_offset= 0; state->flags = search->t2ffirst.in.flags; /* setup for just a header in the reply */ TRANS2_CHECK(trans2_setup_reply(trans, 10, 0, 0)); op->op_info = state; op->send_fn = trans2_findfirst_send; return ntvfs_search_first(req->ntvfs, search, state, find_callback);}/* trans2 findnext send*/static NTSTATUS trans2_findnext_send(struct trans_op *op){ struct smbsrv_request *req = op->req; struct smb_trans2 *trans = op->trans; union smb_search_next *search; struct find_state *state; uint8_t *param; TRANS2_CHECK_ASYNC_STATUS(state, struct find_state); search = talloc_get_type(state->search, union smb_search_next); /* fill in the findfirst reply header */ param = trans->out.params.data; SSVAL(param, VWV(0), search->t2fnext.out.count); SSVAL(param, VWV(1), search->t2fnext.out.end_of_search); SSVAL(param, VWV(2), 0); SSVAL(param, VWV(3), state->last_entry_offset); return NT_STATUS_OK;}/* trans2 findnext implementation*/static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op){ struct smb_trans2 *trans = op->trans; union smb_search_next *search; uint16_t level; struct find_state *state;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -