• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/libcli/smb2/
1/*
2   Unix SMB/CIFS implementation.
3
4   SMB2 client find calls
5
6   Copyright (C) Andrew Tridgell 2005
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "libcli/raw/libcliraw.h"
24#include "libcli/raw/raw_proto.h"
25#include "libcli/smb2/smb2.h"
26#include "libcli/smb2/smb2_calls.h"
27
28/*
29  send a find request
30*/
31struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io)
32{
33	struct smb2_request *req;
34	NTSTATUS status;
35
36	req = smb2_request_init_tree(tree, SMB2_OP_FIND, 0x20, true, 0);
37	if (req == NULL) return NULL;
38
39	SCVAL(req->out.body, 0x02, io->in.level);
40	SCVAL(req->out.body, 0x03, io->in.continue_flags);
41	SIVAL(req->out.body, 0x04, io->in.file_index);
42	smb2_push_handle(req->out.body+0x08, &io->in.file.handle);
43
44	status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern);
45	if (!NT_STATUS_IS_OK(status)) {
46		talloc_free(req);
47		return NULL;
48	}
49
50	SIVAL(req->out.body, 0x1C, io->in.max_response_size);
51
52	smb2_transport_send(req);
53
54	return req;
55}
56
57
58/*
59  recv a find reply
60*/
61NTSTATUS smb2_find_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
62			   struct smb2_find *io)
63{
64	NTSTATUS status;
65
66	if (!smb2_request_receive(req) ||
67	    smb2_request_is_error(req)) {
68		return smb2_request_destroy(req);
69	}
70
71	SMB2_CHECK_PACKET_RECV(req, 0x08, true);
72
73	status = smb2_pull_o16s32_blob(&req->in, mem_ctx,
74				       req->in.body+0x02, &io->out.blob);
75	if (!NT_STATUS_IS_OK(status)) {
76		return status;
77	}
78
79	return smb2_request_destroy(req);
80}
81
82/*
83  sync find request
84*/
85NTSTATUS smb2_find(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
86		   struct smb2_find *io)
87{
88	struct smb2_request *req = smb2_find_send(tree, io);
89	return smb2_find_recv(req, mem_ctx, io);
90}
91
92
93/*
94  a varient of smb2_find_recv that parses the resulting blob into
95  smb_search_data structures
96*/
97NTSTATUS smb2_find_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
98			      uint8_t level, uint_t *count,
99			      union smb_search_data **io)
100{
101	struct smb2_find f;
102	NTSTATUS status;
103	DATA_BLOB b;
104	enum smb_search_data_level smb_level;
105	uint_t next_ofs=0;
106
107	switch (level) {
108	case SMB2_FIND_DIRECTORY_INFO:
109		smb_level = RAW_SEARCH_DATA_DIRECTORY_INFO;
110		break;
111	case SMB2_FIND_FULL_DIRECTORY_INFO:
112		smb_level = RAW_SEARCH_DATA_FULL_DIRECTORY_INFO;
113		break;
114	case SMB2_FIND_BOTH_DIRECTORY_INFO:
115		smb_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
116		break;
117	case SMB2_FIND_NAME_INFO:
118		smb_level = RAW_SEARCH_DATA_NAME_INFO;
119		break;
120	case SMB2_FIND_ID_FULL_DIRECTORY_INFO:
121		smb_level = RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO;
122		break;
123	case SMB2_FIND_ID_BOTH_DIRECTORY_INFO:
124		smb_level = RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO;
125		break;
126	default:
127		return NT_STATUS_INVALID_INFO_CLASS;
128	}
129
130	status = smb2_find_recv(req, mem_ctx, &f);
131	NT_STATUS_NOT_OK_RETURN(status);
132
133	b = f.out.blob;
134	*io = NULL;
135	*count = 0;
136
137	do {
138		union smb_search_data *io2;
139
140		io2 = talloc_realloc(mem_ctx, *io, union smb_search_data, (*count)+1);
141		if (io2 == NULL) {
142			data_blob_free(&f.out.blob);
143			talloc_free(*io);
144			return NT_STATUS_NO_MEMORY;
145		}
146		*io = io2;
147
148		status = smb_raw_search_common(*io, smb_level, &b, (*io) + (*count),
149					       &next_ofs, STR_UNICODE);
150
151		if (NT_STATUS_IS_OK(status) &&
152		    next_ofs >= b.length) {
153			data_blob_free(&f.out.blob);
154			talloc_free(*io);
155			return NT_STATUS_INFO_LENGTH_MISMATCH;
156		}
157
158		(*count)++;
159
160		b = data_blob_const(b.data+next_ofs, b.length - next_ofs);
161	} while (NT_STATUS_IS_OK(status) && next_ofs != 0);
162
163	data_blob_free(&f.out.blob);
164
165	return NT_STATUS_OK;
166}
167
168/*
169  a varient of smb2_find that parses the resulting blob into
170  smb_search_data structures
171*/
172NTSTATUS smb2_find_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
173			 struct smb2_find *f,
174			 uint_t *count, union smb_search_data **io)
175{
176	struct smb2_request *req;
177
178	req = smb2_find_send(tree, f);
179	return smb2_find_level_recv(req, mem_ctx, f->in.level, count, io);
180}
181