/**************************************************************************** check for existance of a trans2 call ****************************************************************************/ static NTSTATUS try_trans2(struct smbcli_state *cli, int op, uint8_t *param, uint8_t *data, int param_len, int data_len, int *rparam_len, int *rdata_len) { NTSTATUS status; struct smb_trans2 t2; uint16_t setup = op; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("try_trans2"); t2.in.max_param = UINT16_MAX; t2.in.max_data = UINT16_MAX; t2.in.max_setup = 10; t2.in.flags = 0; t2.in.timeout = 0; t2.in.setup_count = 1; t2.in.setup = &setup; t2.in.params.data = param; t2.in.params.length = param_len; t2.in.data.data = data; t2.in.data.length = data_len; status = smb_raw_trans2(cli->tree, mem_ctx, &t2); *rparam_len = t2.out.params.length; *rdata_len = t2.out.data.length; talloc_free(mem_ctx); return status; }
/* raw trans2 */ static NTSTATUS cvfs_trans2(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, struct smb_trans2 *trans2) { struct cvfs_private *p = ntvfs->private_data; struct smbcli_request *c_req; if (p->map_trans2) { return NT_STATUS_NOT_IMPLEMENTED; } SETUP_PID; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_trans2(p->tree, req, trans2); } c_req = smb_raw_trans2_send(p->tree, trans2); ASYNC_RECV_TAIL(trans2, async_trans2); }
static BOOL smb_raw_query_posix_whoami(void *mem_ctx, struct torture_context *torture, struct smbcli_state *cli, struct smb_whoami *whoami, unsigned max_data) { struct smb_trans2 tp; NTSTATUS status; size_t offset; int i; uint16_t setup = TRANSACT2_QFSINFO; uint16_t info_level; ZERO_STRUCTP(whoami); tp.in.max_setup = 0; tp.in.flags = 0; tp.in.timeout = 0; tp.in.setup_count = 1; tp.in.max_param = 10; tp.in.max_data = (uint16_t)max_data; tp.in.setup = &setup; tp.in.trans_name = NULL; SSVAL(&info_level, 0, SMB_QFS_POSIX_WHOAMI); tp.in.params = data_blob_talloc(mem_ctx, &info_level, 2); tp.in.data = data_blob_talloc(mem_ctx, NULL, 0); status = smb_raw_trans2(cli->tree, mem_ctx, &tp); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "doing SMB_QFS_POSIX_WHOAMI"); /* Make sure we got back all the required fields. */ torture_assert(torture, tp.out.params.length == 0, "trans2 params should be empty"); torture_assert(torture, tp.out.data.length >= WHOAMI_REQUIRED_SIZE, "checking for required response fields"); whoami->mapping_flags = IVAL(tp.out.data.data, 0); whoami->mapping_mask = IVAL(tp.out.data.data, 4); whoami->server_uid = BVAL(tp.out.data.data, 8); whoami->server_gid = BVAL(tp.out.data.data, 16); whoami->num_gids = IVAL(tp.out.data.data, 24); whoami->num_sids = IVAL(tp.out.data.data, 28); whoami->num_sid_bytes = IVAL(tp.out.data.data, 32); whoami->reserved = IVAL(tp.out.data.data, 36); /* The GID list and SID list are optional, depending on the count * and length fields. */ if (whoami->num_sids != 0) { torture_assert(torture, whoami->num_sid_bytes != 0, "SID count does not match byte count"); } printf("\tmapping_flags=0x%08x mapping_mask=0x%08x\n", whoami->mapping_flags, whoami->mapping_mask); printf("\tserver UID=%lld GID=%lld\n", whoami->server_uid, whoami->server_gid); printf("\t%u GIDs, %u SIDs, %u SID bytes\n", whoami->num_gids, whoami->num_sids, whoami->num_sid_bytes); offset = WHOAMI_REQUIRED_SIZE; torture_assert_int_equal(torture, whoami->reserved, 0, "invalid reserved field"); if (tp.out.data.length == offset) { /* No SIDs or GIDs returned */ torture_assert_int_equal(torture, whoami->num_gids, 0, "invalid GID count"); torture_assert_int_equal(torture, whoami->num_sids, 0, "invalid SID count"); torture_assert_int_equal(torture, whoami->num_sid_bytes, 0, "invalid SID byte count"); return True; } if (whoami->num_gids != 0) { int remain = tp.out.data.length - offset; int gid_bytes = whoami->num_gids * 8; if (whoami->num_sids == 0) { torture_assert_int_equal(torture, remain, gid_bytes, "GID count does not match data length"); } else { torture_assert(torture, remain > gid_bytes, "invalid GID count"); } whoami->gid_list = talloc_array(mem_ctx, uint64_t, whoami->num_gids); torture_assert(torture, whoami->gid_list != NULL, "out of memory"); for (i = 0; i < whoami->num_gids; ++i) { whoami->gid_list[i] = BVAL(tp.out.data.data, offset); offset += 8; } } /* Check if there should be data left for the SID list. */ if (tp.out.data.length == offset) { torture_assert_int_equal(torture, whoami->num_sids, 0, "invalid SID count"); return True; } /* All the remaining bytes must be the SID list. */ torture_assert_int_equal(torture, whoami->num_sid_bytes, (tp.out.data.length - offset), "invalid SID byte count"); if (whoami->num_sids != 0) { whoami->sid_list = talloc_array(mem_ctx, struct dom_sid *, whoami->num_sids); torture_assert(torture, whoami->sid_list != NULL, "out of memory"); for (i = 0; i < whoami->num_sids; ++i) { if (!sid_parse(mem_ctx, torture, &tp.out.data, &offset, &whoami->sid_list[i])) { return False; } } }
/**************************************************************************** Very raw search first - returns param/data blobs. Used in CIFS-on-CIFS NTVFS. ****************************************************************************/ static NTSTATUS smb_raw_search_next_blob(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, union smb_search_next *io, DATA_BLOB *out_param_blob, DATA_BLOB *out_data_blob) { struct smb_trans2 tp; uint16_t setup = TRANSACT2_FINDNEXT; NTSTATUS status; tp.in.max_setup = 0; tp.in.flags = 0; tp.in.timeout = 0; tp.in.setup_count = 1; tp.in.data = data_blob(NULL, 0); tp.in.max_param = 10; tp.in.max_data = 0xFFFF; tp.in.setup = &setup; if (io->t2fnext.level != RAW_SEARCH_TRANS2) { return NT_STATUS_INVALID_LEVEL; } if (io->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) { return NT_STATUS_INVALID_LEVEL; } if (io->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) { if (!ea_push_name_list(mem_ctx, &tp.in.data, io->t2fnext.in.num_names, io->t2fnext.in.ea_names)) { return NT_STATUS_NO_MEMORY; } } tp.in.params = data_blob_talloc(mem_ctx, NULL, 12); if (!tp.in.params.data) { return NT_STATUS_NO_MEMORY; } SSVAL(tp.in.params.data, 0, io->t2fnext.in.handle); SSVAL(tp.in.params.data, 2, io->t2fnext.in.max_count); SSVAL(tp.in.params.data, 4, io->t2fnext.data_level); SIVAL(tp.in.params.data, 6, io->t2fnext.in.resume_key); SSVAL(tp.in.params.data, 10, io->t2fnext.in.flags); smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params, io->t2fnext.in.last_name, STR_TERMINATE); status = smb_raw_trans2(tree, mem_ctx, &tp); if (!NT_STATUS_IS_OK(status)) { return status; } out_param_blob->length = tp.out.params.length; out_param_blob->data = tp.out.params.data; out_data_blob->length = tp.out.data.length; out_data_blob->data = tp.out.data.data; return NT_STATUS_OK; }