/* trans2 mkdir implementation */ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op) { struct smb_trans2 *trans = op->trans; union smb_mkdir *io; /* make sure we got enough parameters */ if (trans->in.params.length < 5) { return NT_STATUS_FOOBAR; } io = talloc(op, union smb_mkdir); NT_STATUS_HAVE_NO_MEMORY(io); io->t2mkdir.level = RAW_MKDIR_T2MKDIR; smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, &io->t2mkdir.in.path, 0); if (io->t2mkdir.in.path == NULL) { return NT_STATUS_FOOBAR; } TRANS2_CHECK(ea_pull_list(&trans->in.data, io, &io->t2mkdir.in.num_eas, &io->t2mkdir.in.eas)); op->op_info = io; op->send_fn = trans2_simple_send; return ntvfs_mkdir(req->ntvfs, io); }
/* trans2 open implementation */ static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op) { struct smb_trans2 *trans = op->trans; union smb_open *io; /* make sure we got enough parameters */ if (trans->in.params.length < 29) { return NT_STATUS_FOOBAR; } io = talloc(op, union smb_open); NT_STATUS_HAVE_NO_MEMORY(io); io->t2open.level = RAW_OPEN_T2OPEN; io->t2open.in.flags = SVAL(trans->in.params.data, VWV(0)); io->t2open.in.open_mode = SVAL(trans->in.params.data, VWV(1)); io->t2open.in.search_attrs = SVAL(trans->in.params.data, VWV(2)); io->t2open.in.file_attrs = SVAL(trans->in.params.data, VWV(3)); io->t2open.in.write_time = srv_pull_dos_date(req->smb_conn, trans->in.params.data + VWV(4)); io->t2open.in.open_func = SVAL(trans->in.params.data, VWV(6)); io->t2open.in.size = IVAL(trans->in.params.data, VWV(7)); io->t2open.in.timeout = IVAL(trans->in.params.data, VWV(9)); io->t2open.in.num_eas = 0; io->t2open.in.eas = NULL; smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 28, &io->t2open.in.fname, 0); if (io->t2open.in.fname == NULL) { return NT_STATUS_FOOBAR; } TRANS2_CHECK(ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas)); op->op_info = io; op->send_fn = trans2_open_send; return ntvfs_open(req->ntvfs, io); }
/* parse a trans2 search response. Return the number of bytes consumed return 0 for success with end of list return -1 for a parse error */ static int parse_trans2_search(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, enum smb_search_data_level level, uint16_t flags, DATA_BLOB *blob, union smb_search_data *data) { unsigned int len, ofs; uint32_t ea_size; DATA_BLOB eablob; NTSTATUS status; switch (level) { case RAW_SEARCH_DATA_GENERIC: case RAW_SEARCH_DATA_SEARCH: /* handled elsewhere */ return -1; case RAW_SEARCH_DATA_STANDARD: if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { if (blob->length < 4) return -1; data->standard.resume_key = IVAL(blob->data, 0); blob->data += 4; blob->length -= 4; } if (blob->length < 24) return -1; data->standard.create_time = raw_pull_dos_date2(tree->session->transport, blob->data + 0); data->standard.access_time = raw_pull_dos_date2(tree->session->transport, blob->data + 4); data->standard.write_time = raw_pull_dos_date2(tree->session->transport, blob->data + 8); data->standard.size = IVAL(blob->data, 12); data->standard.alloc_size = IVAL(blob->data, 16); data->standard.attrib = SVAL(blob->data, 20); len = smbcli_blob_pull_string(tree->session, mem_ctx, blob, &data->standard.name, 22, 23, STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM); return len + 23; case RAW_SEARCH_DATA_EA_SIZE: if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { if (blob->length < 4) return -1; data->ea_size.resume_key = IVAL(blob->data, 0); blob->data += 4; blob->length -= 4; } if (blob->length < 28) return -1; data->ea_size.create_time = raw_pull_dos_date2(tree->session->transport, blob->data + 0); data->ea_size.access_time = raw_pull_dos_date2(tree->session->transport, blob->data + 4); data->ea_size.write_time = raw_pull_dos_date2(tree->session->transport, blob->data + 8); data->ea_size.size = IVAL(blob->data, 12); data->ea_size.alloc_size = IVAL(blob->data, 16); data->ea_size.attrib = SVAL(blob->data, 20); data->ea_size.ea_size = IVAL(blob->data, 22); len = smbcli_blob_pull_string(tree->session, mem_ctx, blob, &data->ea_size.name, 26, 27, STR_LEN8BIT | STR_TERMINATE | STR_NOALIGN); return len + 27 + 1; case RAW_SEARCH_DATA_EA_LIST: if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) { if (blob->length < 4) return -1; data->ea_list.resume_key = IVAL(blob->data, 0); blob->data += 4; blob->length -= 4; } if (blob->length < 28) return -1; data->ea_list.create_time = raw_pull_dos_date2(tree->session->transport, blob->data + 0); data->ea_list.access_time = raw_pull_dos_date2(tree->session->transport, blob->data + 4); data->ea_list.write_time = raw_pull_dos_date2(tree->session->transport, blob->data + 8); data->ea_list.size = IVAL(blob->data, 12); data->ea_list.alloc_size = IVAL(blob->data, 16); data->ea_list.attrib = SVAL(blob->data, 20); ea_size = IVAL(blob->data, 22); if (ea_size > 0xFFFF) { return -1; } eablob.data = blob->data + 22; eablob.length = ea_size; if (eablob.length > blob->length - 24) { return -1; } status = ea_pull_list(&eablob, mem_ctx, &data->ea_list.eas.num_eas, &data->ea_list.eas.eas); if (!NT_STATUS_IS_OK(status)) { return -1; } len = smbcli_blob_pull_string(tree->session, mem_ctx, blob, &data->ea_list.name, 22+ea_size, 23+ea_size, STR_LEN8BIT | STR_NOALIGN); return len + ea_size + 23 + 1; case RAW_SEARCH_DATA_UNIX_INFO: if (blob->length < 109) return -1; ofs = IVAL(blob->data, 0); data->unix_info.file_index = IVAL(blob->data, 4); data->unix_info.size = BVAL(blob->data, 8); data->unix_info.alloc_size = BVAL(blob->data, 16); data->unix_info.status_change_time = smbcli_pull_nttime(blob->data, 24); data->unix_info.access_time = smbcli_pull_nttime(blob->data, 32); data->unix_info.change_time = smbcli_pull_nttime(blob->data, 40); data->unix_info.uid = IVAL(blob->data, 48); data->unix_info.gid = IVAL(blob->data, 56); data->unix_info.file_type = IVAL(blob->data, 64); data->unix_info.dev_major = BVAL(blob->data, 68); data->unix_info.dev_minor = BVAL(blob->data, 76); data->unix_info.unique_id = BVAL(blob->data, 84); data->unix_info.permissions = IVAL(blob->data, 92); data->unix_info.nlink = IVAL(blob->data, 100); /* There is no length field for this name but we know it's null terminated. */ len = smbcli_blob_pull_unix_string(tree->session, mem_ctx, blob, &data->unix_info.name, 108, 0); if (ofs != 0 && ofs < 108+len) { return -1; } return ofs; case RAW_SEARCH_DATA_UNIX_INFO2: /* 8 - size of ofs + file_index * 116 - size of unix_info2 * 4 - size of name length * 2 - "." is the shortest name */ if (blob->length < (116 + 8 + 4 + 2)) { return -1; } ofs = IVAL(blob->data, 0); data->unix_info2.file_index = IVAL(blob->data, 4); data->unix_info2.end_of_file = BVAL(blob->data, 8); data->unix_info2.num_bytes = BVAL(blob->data, 16); data->unix_info2.status_change_time = smbcli_pull_nttime(blob->data, 24); data->unix_info2.access_time = smbcli_pull_nttime(blob->data, 32); data->unix_info2.change_time = smbcli_pull_nttime(blob->data, 40); data->unix_info2.uid = IVAL(blob->data, 48); data->unix_info2.gid = IVAL(blob->data, 56); data->unix_info2.file_type = IVAL(blob->data, 64); data->unix_info2.dev_major = BVAL(blob->data, 68); data->unix_info2.dev_minor = BVAL(blob->data, 76); data->unix_info2.unique_id = BVAL(blob->data, 84); data->unix_info2.permissions = IVAL(blob->data, 92); data->unix_info2.nlink = IVAL(blob->data, 100); data->unix_info2.create_time = smbcli_pull_nttime(blob->data, 108); data->unix_info2.file_flags = IVAL(blob->data, 116); data->unix_info2.flags_mask = IVAL(blob->data, 120); /* There is a 4 byte length field for this name. The length * does not include the NULL terminator. */ len = smbcli_blob_pull_string(tree->session, mem_ctx, blob, &data->unix_info2.name, 8 + 116, /* offset to length */ 8 + 116 + 4, /* offset to string */ 0); if (ofs != 0 && ofs < (8 + 116 + 4 + len)) { return -1; } return ofs; 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: { unsigned int str_flags = STR_UNICODE; if (!(tree->session->transport->negotiate.capabilities & CAP_UNICODE)) { str_flags = STR_ASCII; } status = smb_raw_search_common(mem_ctx, level, blob, data, &ofs, str_flags); if (!NT_STATUS_IS_OK(status)) { return -1; } return ofs; } } /* invalid level */ return -1; }
/* 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_PIPE_INFORMATION: case RAW_SFILEINFO_VALID_DATA_INFORMATION: case RAW_SFILEINFO_SHORT_NAME_INFORMATION: case RAW_SFILEINFO_1025: case RAW_SFILEINFO_1027: case RAW_SFILEINFO_1029: case RAW_SFILEINFO_1030: case RAW_SFILEINFO_1031: case RAW_SFILEINFO_1032: case RAW_SFILEINFO_1036: case RAW_SFILEINFO_1041: case RAW_SFILEINFO_1042: case RAW_SFILEINFO_1043: case RAW_SFILEINFO_1044: 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); }