Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : raw trans/trans2/nttrans operations
4 :
5 : Copyright (C) James Myers 2003 <myersjj@samba.org>
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include <tevent.h>
23 : #include "libcli/raw/libcliraw.h"
24 : #include "libcli/raw/raw_proto.h"
25 : #include "../libcli/smb/smbXcli_base.h"
26 :
27 : static void smb_raw_trans_backend_done(struct tevent_req *subreq);
28 :
29 55432 : static struct smbcli_request *smb_raw_trans_backend_send(struct smbcli_tree *tree,
30 : struct smb_trans2 *parms,
31 : uint8_t command)
32 : {
33 1218 : struct smbcli_request *req;
34 1218 : uint8_t additional_flags;
35 1218 : uint8_t clear_flags;
36 1218 : uint16_t additional_flags2;
37 1218 : uint16_t clear_flags2;
38 1218 : uint32_t pid;
39 55432 : struct smbXcli_tcon *tcon = NULL;
40 55432 : struct smbXcli_session *session = NULL;
41 55432 : const char *pipe_name = NULL;
42 1218 : uint8_t s;
43 1218 : uint32_t timeout_msec;
44 1218 : uint32_t tmp;
45 :
46 55432 : tmp = parms->in.params.length + parms->in.data.length;
47 :
48 55432 : req = smbcli_request_setup(tree, command, parms->in.setup_count, tmp);
49 55432 : if (req == NULL) {
50 0 : return NULL;
51 : }
52 :
53 55432 : additional_flags = CVAL(req->out.hdr, HDR_FLG);
54 55432 : additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
55 55432 : pid = SVAL(req->out.hdr, HDR_PID);
56 55432 : pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
57 :
58 55432 : if (req->session) {
59 55432 : session = req->session->smbXcli;
60 : }
61 :
62 55432 : if (req->tree) {
63 55432 : tcon = req->tree->smbXcli;
64 : }
65 :
66 55432 : clear_flags = ~additional_flags;
67 55432 : clear_flags2 = ~additional_flags2;
68 :
69 55432 : timeout_msec = req->transport->options.request_timeout * 1000;
70 :
71 110774 : for (s=0; s < parms->in.setup_count; s++) {
72 55342 : SSVAL(req->out.vwv, VWV(s), parms->in.setup[s]);
73 : }
74 :
75 55432 : if (parms->in.params.length > 0) {
76 56650 : memcpy(req->out.data,
77 55432 : parms->in.params.data,
78 : parms->in.params.length);
79 : }
80 55432 : if (parms->in.data.length > 0) {
81 11868 : memcpy(req->out.data + parms->in.params.length,
82 10650 : parms->in.data.data,
83 : parms->in.data.length);
84 : }
85 :
86 55432 : if (command == SMBtrans && parms->in.trans_name) {
87 90 : pipe_name = parms->in.trans_name;
88 : }
89 :
90 110864 : req->subreqs[0] = smb1cli_trans_send(req,
91 54214 : req->transport->ev,
92 55432 : req->transport->conn,
93 : command,
94 : additional_flags,
95 : clear_flags,
96 : additional_flags2,
97 : clear_flags2,
98 : timeout_msec,
99 : pid,
100 : tcon,
101 : session,
102 : pipe_name,
103 : 0xFFFF, /* fid */
104 : 0, /* function */
105 55432 : parms->in.flags,
106 55432 : (uint16_t *)req->out.vwv,
107 55432 : parms->in.setup_count,
108 55432 : parms->in.max_setup,
109 : req->out.data,
110 54214 : parms->in.params.length,
111 55432 : parms->in.max_param,
112 55432 : req->out.data+
113 55432 : parms->in.params.length,
114 55432 : parms->in.data.length,
115 55432 : parms->in.max_data);
116 55432 : if (req->subreqs[0] == NULL) {
117 0 : talloc_free(req);
118 0 : return NULL;
119 : }
120 55432 : tevent_req_set_callback(req->subreqs[0],
121 : smb_raw_trans_backend_done,
122 : req);
123 :
124 55432 : return req;
125 : }
126 :
127 55432 : static void smb_raw_trans_backend_done(struct tevent_req *subreq)
128 : {
129 1218 : struct smbcli_request *req =
130 55432 : tevent_req_callback_data(subreq,
131 : struct smbcli_request);
132 55432 : struct smbcli_transport *transport = req->transport;
133 55432 : uint16_t *setup = NULL;
134 55432 : uint8_t num_setup = 0;
135 1218 : uint8_t s;
136 55432 : uint8_t *param = NULL;
137 55432 : uint32_t num_param = 0;
138 55432 : uint8_t *data = NULL;
139 55432 : uint32_t num_data = 0;
140 :
141 55432 : req->status = smb1cli_trans_recv(req->subreqs[0], req,
142 : &req->flags2,
143 : &setup,
144 : 0, /* min_setup */
145 : &num_setup,
146 : ¶m,
147 : 0, /* min_param */
148 : &num_param,
149 : &data,
150 : 0, /* min_data */
151 : &num_data);
152 55432 : TALLOC_FREE(req->subreqs[0]);
153 55432 : if (NT_STATUS_IS_ERR(req->status)) {
154 30590 : req->state = SMBCLI_REQUEST_ERROR;
155 30590 : transport->error.e.nt_status = req->status;
156 30590 : transport->error.etype = ETYPE_SMB;
157 30590 : if (req->async.fn) {
158 5950 : req->async.fn(req);
159 : }
160 30590 : return;
161 : }
162 :
163 24842 : req->trans2.out.setup_count = num_setup;
164 24842 : req->trans2.out.setup = talloc_array(req, uint16_t, num_setup);
165 24842 : if (req->trans2.out.setup == NULL) {
166 0 : req->state = SMBCLI_REQUEST_ERROR;
167 0 : req->status = NT_STATUS_NO_MEMORY;
168 0 : transport->error.e.nt_status = req->status;
169 0 : transport->error.etype = ETYPE_SMB;
170 0 : if (req->async.fn) {
171 0 : req->async.fn(req);
172 : }
173 0 : return;
174 : }
175 24842 : for (s = 0; s < num_setup; s++) {
176 0 : req->trans2.out.setup[s] = SVAL(setup, VWV(s));
177 : }
178 :
179 24842 : req->trans2.out.params.data = param;
180 24842 : req->trans2.out.params.length = num_param;
181 :
182 24842 : req->trans2.out.data.data = data;
183 24842 : req->trans2.out.data.length = num_data;
184 :
185 24842 : transport->error.e.nt_status = req->status;
186 24842 : if (NT_STATUS_IS_OK(req->status)) {
187 24607 : transport->error.etype = ETYPE_NONE;
188 : } else {
189 235 : transport->error.etype = ETYPE_SMB;
190 : }
191 :
192 24842 : req->state = SMBCLI_REQUEST_DONE;
193 24842 : if (req->async.fn) {
194 393 : req->async.fn(req);
195 : }
196 : }
197 :
198 49457 : static NTSTATUS smb_raw_trans_backend_recv(struct smbcli_request *req,
199 : TALLOC_CTX *mem_ctx,
200 : struct smb_trans2 *parms)
201 : {
202 68886 : if (!smbcli_request_receive(req) ||
203 19429 : smbcli_request_is_error(req)) {
204 30028 : goto failed;
205 : }
206 :
207 19429 : parms->out = req->trans2.out;
208 19429 : talloc_steal(mem_ctx, parms->out.setup);
209 19429 : talloc_steal(mem_ctx, parms->out.params.data);
210 19429 : talloc_steal(mem_ctx, parms->out.data.data);
211 :
212 49457 : failed:
213 49457 : return smbcli_request_destroy(req);
214 : }
215 :
216 90 : _PUBLIC_ struct smbcli_request *smb_raw_trans_send(struct smbcli_tree *tree,
217 : struct smb_trans2 *parms)
218 : {
219 90 : return smb_raw_trans_backend_send(tree, parms, SMBtrans);
220 : }
221 :
222 90 : _PUBLIC_ NTSTATUS smb_raw_trans_recv(struct smbcli_request *req,
223 : TALLOC_CTX *mem_ctx,
224 : struct smb_trans2 *parms)
225 : {
226 90 : return smb_raw_trans_backend_recv(req, mem_ctx, parms);
227 : }
228 :
229 90 : _PUBLIC_ NTSTATUS smb_raw_trans(struct smbcli_tree *tree,
230 : TALLOC_CTX *mem_ctx,
231 : struct smb_trans2 *parms)
232 : {
233 0 : struct smbcli_request *req;
234 90 : req = smb_raw_trans_send(tree, parms);
235 90 : if (!req) return NT_STATUS_UNSUCCESSFUL;
236 90 : return smb_raw_trans_recv(req, mem_ctx, parms);
237 : }
238 :
239 55342 : struct smbcli_request *smb_raw_trans2_send(struct smbcli_tree *tree,
240 : struct smb_trans2 *parms)
241 : {
242 55342 : return smb_raw_trans_backend_send(tree, parms, SMBtrans2);
243 : }
244 :
245 49367 : NTSTATUS smb_raw_trans2_recv(struct smbcli_request *req,
246 : TALLOC_CTX *mem_ctx,
247 : struct smb_trans2 *parms)
248 : {
249 49367 : return smb_raw_trans_backend_recv(req, mem_ctx, parms);
250 : }
251 :
252 35298 : NTSTATUS smb_raw_trans2(struct smbcli_tree *tree,
253 : TALLOC_CTX *mem_ctx,
254 : struct smb_trans2 *parms)
255 : {
256 175 : struct smbcli_request *req;
257 35298 : req = smb_raw_trans2_send(tree, parms);
258 35298 : if (!req) return NT_STATUS_UNSUCCESSFUL;
259 35298 : return smb_raw_trans2_recv(req, mem_ctx, parms);
260 : }
261 :
262 : static void smb_raw_nttrans_done(struct tevent_req *subreq);
263 :
264 17196 : struct smbcli_request *smb_raw_nttrans_send(struct smbcli_tree *tree,
265 : struct smb_nttrans *parms)
266 : {
267 65 : struct smbcli_request *req;
268 65 : uint8_t additional_flags;
269 65 : uint8_t clear_flags;
270 65 : uint16_t additional_flags2;
271 65 : uint16_t clear_flags2;
272 65 : uint32_t pid;
273 17196 : struct smbXcli_tcon *tcon = NULL;
274 17196 : struct smbXcli_session *session = NULL;
275 65 : uint32_t timeout_msec;
276 65 : uint32_t tmp;
277 :
278 17196 : tmp = parms->in.params.length + parms->in.data.length;
279 :
280 17196 : req = smbcli_request_setup(tree, SMBnttrans, parms->in.setup_count, tmp);
281 17196 : if (req == NULL) {
282 0 : return NULL;
283 : }
284 :
285 17196 : additional_flags = CVAL(req->out.hdr, HDR_FLG);
286 17196 : additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
287 17196 : pid = SVAL(req->out.hdr, HDR_PID);
288 17196 : pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
289 :
290 17196 : if (req->session) {
291 17196 : session = req->session->smbXcli;
292 : }
293 :
294 17196 : if (req->tree) {
295 17196 : tcon = req->tree->smbXcli;
296 : }
297 :
298 17196 : clear_flags = ~additional_flags;
299 17196 : clear_flags2 = ~additional_flags2;
300 :
301 17196 : timeout_msec = req->transport->options.request_timeout * 1000;
302 :
303 17196 : if (parms->in.setup_count > 0) {
304 1712 : memcpy(
305 1647 : req->out.vwv, parms->in.setup, parms->in.setup_count * 2);
306 : }
307 :
308 17196 : if (parms->in.params.length > 0) {
309 15614 : memcpy(req->out.data,
310 15549 : parms->in.params.data,
311 : parms->in.params.length);
312 : }
313 17196 : if (parms->in.data.length > 0) {
314 7339 : memcpy(req->out.data + parms->in.params.length,
315 7274 : parms->in.data.data,
316 : parms->in.data.length);
317 : }
318 :
319 34392 : req->subreqs[0] = smb1cli_trans_send(req,
320 17131 : req->transport->ev,
321 17196 : req->transport->conn,
322 : SMBnttrans,
323 : additional_flags,
324 : clear_flags,
325 : additional_flags2,
326 : clear_flags2,
327 : timeout_msec,
328 : pid,
329 : tcon,
330 : session,
331 : NULL, /* pipe_name */
332 : 0xFFFF, /* fid */
333 17196 : parms->in.function,
334 : 0, /* flags */
335 17196 : (uint16_t *)req->out.vwv,
336 17196 : parms->in.setup_count,
337 17196 : parms->in.max_setup,
338 : req->out.data,
339 17131 : parms->in.params.length,
340 : parms->in.max_param,
341 17196 : req->out.data+
342 17196 : parms->in.params.length,
343 17196 : parms->in.data.length,
344 : parms->in.max_data);
345 17196 : if (req->subreqs[0] == NULL) {
346 0 : talloc_free(req);
347 0 : return NULL;
348 : }
349 17196 : tevent_req_set_callback(req->subreqs[0],
350 : smb_raw_nttrans_done,
351 : req);
352 :
353 17196 : return req;
354 : }
355 :
356 17196 : static void smb_raw_nttrans_done(struct tevent_req *subreq)
357 : {
358 65 : struct smbcli_request *req =
359 17196 : tevent_req_callback_data(subreq,
360 : struct smbcli_request);
361 17196 : struct smbcli_transport *transport = req->transport;
362 17196 : uint16_t *setup = NULL;
363 17196 : uint8_t num_setup = 0;
364 17196 : uint8_t *param = NULL;
365 17196 : uint32_t num_param = 0;
366 17196 : uint8_t *data = NULL;
367 17196 : uint32_t num_data = 0;
368 :
369 17196 : req->status = smb1cli_trans_recv(req->subreqs[0], req,
370 : &req->flags2,
371 : &setup,
372 : 0, /* min_setup */
373 : &num_setup,
374 : ¶m,
375 : 0, /* min_param */
376 : &num_param,
377 : &data,
378 : 0, /* min_data */
379 : &num_data);
380 17196 : TALLOC_FREE(req->subreqs[0]);
381 17196 : if (NT_STATUS_IS_ERR(req->status)) {
382 1603 : req->state = SMBCLI_REQUEST_ERROR;
383 1603 : transport->error.e.nt_status = req->status;
384 1603 : transport->error.etype = ETYPE_SMB;
385 1603 : if (req->async.fn) {
386 11 : req->async.fn(req);
387 : }
388 1603 : return;
389 : }
390 :
391 15593 : req->nttrans.out.setup_count = num_setup;
392 15593 : req->nttrans.out.setup = (uint8_t *)setup;
393 :
394 15593 : req->nttrans.out.params.data = param;
395 15593 : req->nttrans.out.params.length = num_param;
396 :
397 15593 : req->nttrans.out.data.data = data;
398 15593 : req->nttrans.out.data.length = num_data;
399 :
400 15593 : transport->error.e.nt_status = req->status;
401 15593 : if (NT_STATUS_IS_OK(req->status)) {
402 15588 : transport->error.etype = ETYPE_NONE;
403 : } else {
404 5 : transport->error.etype = ETYPE_SMB;
405 : }
406 :
407 15593 : req->state = SMBCLI_REQUEST_DONE;
408 15593 : if (req->async.fn) {
409 1503 : req->async.fn(req);
410 : }
411 : }
412 :
413 9968 : NTSTATUS smb_raw_nttrans_recv(struct smbcli_request *req,
414 : TALLOC_CTX *mem_ctx,
415 : struct smb_nttrans *parms)
416 : {
417 18501 : if (!smbcli_request_receive(req) ||
418 8533 : smbcli_request_is_error(req)) {
419 1435 : goto failed;
420 : }
421 :
422 8533 : parms->out = req->nttrans.out;
423 8533 : talloc_steal(mem_ctx, parms->out.setup);
424 8533 : talloc_steal(mem_ctx, parms->out.params.data);
425 8533 : talloc_steal(mem_ctx, parms->out.data.data);
426 :
427 9968 : failed:
428 9968 : return smbcli_request_destroy(req);
429 : }
430 :
431 : /****************************************************************************
432 : receive a SMB nttrans response allocating the necessary memory
433 : ****************************************************************************/
434 0 : NTSTATUS smb_raw_nttrans(struct smbcli_tree *tree,
435 : TALLOC_CTX *mem_ctx,
436 : struct smb_nttrans *parms)
437 : {
438 0 : struct smbcli_request *req;
439 :
440 0 : req = smb_raw_nttrans_send(tree, parms);
441 0 : if (!req) {
442 0 : return NT_STATUS_UNSUCCESSFUL;
443 : }
444 :
445 0 : return smb_raw_nttrans_recv(req, mem_ctx, parms);
446 : }
|