/**************************************************************************** Open a file using TRANSACT2_OPEN - async send ****************************************************************************/ static struct smbcli_request *smb_raw_t2open_send(struct smbcli_tree *tree, union smb_open *parms) { struct smb_trans2 t2; uint16_t setup = TRANSACT2_OPEN; TALLOC_CTX *mem_ctx = talloc_init("smb_raw_t2open"); struct smbcli_request *req; uint16_t list_size; list_size = ea_list_size(parms->t2open.in.num_eas, parms->t2open.in.eas); t2.in.max_param = 30; t2.in.max_data = 0; t2.in.max_setup = 0; t2.in.flags = 0; t2.in.timeout = 0; t2.in.setup_count = 1; t2.in.setup = &setup; t2.in.params = data_blob_talloc(mem_ctx, NULL, 28); t2.in.data = data_blob_talloc(mem_ctx, NULL, list_size); SSVAL(t2.in.params.data, VWV(0), parms->t2open.in.flags); SSVAL(t2.in.params.data, VWV(1), parms->t2open.in.open_mode); SSVAL(t2.in.params.data, VWV(2), parms->t2open.in.search_attrs); SSVAL(t2.in.params.data, VWV(3), parms->t2open.in.file_attrs); raw_push_dos_date(tree->session->transport, t2.in.params.data, VWV(4), parms->t2open.in.write_time); SSVAL(t2.in.params.data, VWV(6), parms->t2open.in.open_func); SIVAL(t2.in.params.data, VWV(7), parms->t2open.in.size); SIVAL(t2.in.params.data, VWV(9), parms->t2open.in.timeout); SIVAL(t2.in.params.data, VWV(11), 0); SSVAL(t2.in.params.data, VWV(13), 0); smbcli_blob_append_string(tree->session, mem_ctx, &t2.in.params, parms->t2open.in.fname, STR_TERMINATE); ea_put_list(t2.in.data.data, parms->t2open.in.num_eas, parms->t2open.in.eas); req = smb_raw_trans2_send(tree, &t2); talloc_free(mem_ctx); return req; }
/**************************************************************************** create a directory using TRANSACT2_MKDIR - async interface ****************************************************************************/ static struct smbcli_request *smb_raw_t2mkdir_send(struct smbcli_tree *tree, union smb_mkdir *parms) { struct smb_trans2 t2; uint16_t setup = TRANSACT2_MKDIR; TALLOC_CTX *mem_ctx; struct smbcli_request *req; uint16_t data_total; mem_ctx = talloc_init("t2mkdir"); data_total = ea_list_size(parms->t2mkdir.in.num_eas, parms->t2mkdir.in.eas); t2.in.max_param = 2; t2.in.max_data = 0; t2.in.max_setup = 0; t2.in.flags = 0; t2.in.timeout = 0; t2.in.setup_count = 1; t2.in.setup = &setup; t2.in.params = data_blob_talloc(mem_ctx, NULL, 4); t2.in.data = data_blob_talloc(mem_ctx, NULL, data_total); SIVAL(t2.in.params.data, VWV(0), 0); /* reserved */ smbcli_blob_append_string(tree->session, mem_ctx, &t2.in.params, parms->t2mkdir.in.path, STR_TERMINATE); ea_put_list(t2.in.data.data, parms->t2mkdir.in.num_eas, parms->t2mkdir.in.eas); req = smb_raw_trans2_send(tree, &t2); talloc_free(mem_ctx); return req; }
/* 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; unsigned int 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: case RAW_SEARCH_DATA_UNIX_INFO2: return NT_STATUS_INVALID_LEVEL; } return NT_STATUS_OK; }
static NTSTATUS trans2_push_fileinfo(struct smbsrv_connection *smb_conn, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, union smb_fileinfo *st, int default_str_flags) { uint32_t list_size; enum smb_fileinfo_level passthru_level; switch (st->generic.level) { case RAW_FILEINFO_GENERIC: case RAW_FILEINFO_GETATTR: case RAW_FILEINFO_GETATTRE: case RAW_FILEINFO_SEC_DESC: case RAW_FILEINFO_SMB2_ALL_EAS: case RAW_FILEINFO_SMB2_ALL_INFORMATION: /* handled elsewhere */ return NT_STATUS_INVALID_LEVEL; case RAW_FILEINFO_UNIX_BASIC: case RAW_FILEINFO_UNIX_LINK: /* not implemented yet */ return NT_STATUS_INVALID_LEVEL; case RAW_FILEINFO_STANDARD: TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 22)); srv_push_dos_date2(smb_conn, blob->data, 0, st->standard.out.create_time); srv_push_dos_date2(smb_conn, blob->data, 4, st->standard.out.access_time); srv_push_dos_date2(smb_conn, blob->data, 8, st->standard.out.write_time); SIVAL(blob->data, 12, st->standard.out.size); SIVAL(blob->data, 16, st->standard.out.alloc_size); SSVAL(blob->data, 20, st->standard.out.attrib); return NT_STATUS_OK; case RAW_FILEINFO_EA_SIZE: TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 26)); srv_push_dos_date2(smb_conn, blob->data, 0, st->ea_size.out.create_time); srv_push_dos_date2(smb_conn, blob->data, 4, st->ea_size.out.access_time); srv_push_dos_date2(smb_conn, blob->data, 8, st->ea_size.out.write_time); SIVAL(blob->data, 12, st->ea_size.out.size); SIVAL(blob->data, 16, st->ea_size.out.alloc_size); SSVAL(blob->data, 20, st->ea_size.out.attrib); SIVAL(blob->data, 22, st->ea_size.out.ea_size); return NT_STATUS_OK; case RAW_FILEINFO_EA_LIST: list_size = ea_list_size(st->ea_list.out.num_eas, st->ea_list.out.eas); TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size)); ea_put_list(blob->data, st->ea_list.out.num_eas, st->ea_list.out.eas); return NT_STATUS_OK; case RAW_FILEINFO_ALL_EAS: list_size = ea_list_size(st->all_eas.out.num_eas, st->all_eas.out.eas); TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size)); ea_put_list(blob->data, st->all_eas.out.num_eas, st->all_eas.out.eas); return NT_STATUS_OK; case RAW_FILEINFO_IS_NAME_VALID: return NT_STATUS_OK; case RAW_FILEINFO_BASIC_INFO: passthru_level = RAW_FILEINFO_BASIC_INFORMATION; break; case RAW_FILEINFO_STANDARD_INFO: passthru_level = RAW_FILEINFO_STANDARD_INFORMATION; break; case RAW_FILEINFO_EA_INFO: passthru_level = RAW_FILEINFO_EA_INFORMATION; break; case RAW_FILEINFO_COMPRESSION_INFO: passthru_level = RAW_FILEINFO_COMPRESSION_INFORMATION; break; case RAW_FILEINFO_ALL_INFO: passthru_level = RAW_FILEINFO_ALL_INFORMATION; break; case RAW_FILEINFO_NAME_INFO: passthru_level = RAW_FILEINFO_NAME_INFORMATION; break; case RAW_FILEINFO_ALT_NAME_INFO: passthru_level = RAW_FILEINFO_ALT_NAME_INFORMATION; break; case RAW_FILEINFO_STREAM_INFO: passthru_level = RAW_FILEINFO_STREAM_INFORMATION; break; default: passthru_level = st->generic.level; break; } return smbsrv_push_passthru_fileinfo(mem_ctx, blob, passthru_level, st, default_str_flags); }