Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Andrew Tridgell 2003
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /*
21 : this file implements functions for manipulating the 'struct smbsrv_request' structure in smbd
22 : */
23 :
24 : #include "includes.h"
25 : #include "smb_server/smb_server.h"
26 : #include "samba/service_stream.h"
27 : #include "lib/stream/packet.h"
28 : #include "ntvfs/ntvfs.h"
29 :
30 :
31 : /* we over allocate the data buffer to prevent too many realloc calls */
32 : #define REQ_OVER_ALLOCATION 0
33 :
34 : /* setup the bufinfo used for strings and range checking */
35 423211 : void smbsrv_setup_bufinfo(struct smbsrv_request *req)
36 : {
37 423211 : req->in.bufinfo.mem_ctx = req;
38 423211 : req->in.bufinfo.flags = 0;
39 423211 : if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
40 423202 : req->in.bufinfo.flags |= BUFINFO_FLAG_UNICODE;
41 : }
42 423211 : req->in.bufinfo.align_base = req->in.buffer;
43 423211 : req->in.bufinfo.data = req->in.data;
44 423211 : req->in.bufinfo.data_size = req->in.data_size;
45 423211 : }
46 :
47 :
48 423260 : static int smbsrv_request_destructor(struct smbsrv_request *req)
49 : {
50 423260 : DLIST_REMOVE(req->smb_conn->requests, req);
51 423260 : return 0;
52 : }
53 :
54 : /****************************************************************************
55 : construct a basic request packet, mostly used to construct async packets
56 : such as change notify and oplock break requests
57 : ****************************************************************************/
58 423260 : struct smbsrv_request *smbsrv_init_request(struct smbsrv_connection *smb_conn)
59 : {
60 0 : struct smbsrv_request *req;
61 :
62 423260 : req = talloc_zero(smb_conn, struct smbsrv_request);
63 423260 : if (!req) {
64 0 : return NULL;
65 : }
66 :
67 : /* setup the request context */
68 423260 : req->smb_conn = smb_conn;
69 :
70 423260 : talloc_set_destructor(req, smbsrv_request_destructor);
71 :
72 423260 : return req;
73 : }
74 :
75 :
76 : /*
77 : setup a chained reply in req->out with the given word count and initial data buffer size.
78 : */
79 8 : static void req_setup_chain_reply(struct smbsrv_request *req, unsigned int wct, unsigned int buflen)
80 : {
81 8 : uint32_t chain_base_size = req->out.size;
82 :
83 : /* we need room for the wct value, the words, the buffer length and the buffer */
84 8 : req->out.size += 1 + VWV(wct) + 2 + buflen;
85 :
86 : /* over allocate by a small amount */
87 8 : req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
88 :
89 8 : req->out.buffer = talloc_realloc(req, req->out.buffer,
90 : uint8_t, req->out.allocated);
91 8 : if (!req->out.buffer) {
92 0 : smbsrv_terminate_connection(req->smb_conn, "allocation failed");
93 0 : return;
94 : }
95 :
96 8 : req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
97 8 : req->out.vwv = req->out.buffer + chain_base_size + 1;
98 8 : req->out.wct = wct;
99 8 : req->out.data = req->out.vwv + VWV(wct) + 2;
100 8 : req->out.data_size = buflen;
101 8 : req->out.ptr = req->out.data;
102 :
103 8 : SCVAL(req->out.buffer, chain_base_size, wct);
104 8 : SSVAL(req->out.vwv, VWV(wct), buflen);
105 : }
106 :
107 :
108 : /*
109 : setup a reply in req->out with the given word count and initial data buffer size.
110 : the caller will then fill in the command words and data before calling req_send_reply() to
111 : send the reply on its way
112 : */
113 440293 : void smbsrv_setup_reply(struct smbsrv_request *req, unsigned int wct, size_t buflen)
114 : {
115 0 : uint16_t flags2;
116 :
117 440293 : if (req->chain_count != 0) {
118 8 : req_setup_chain_reply(req, wct, buflen);
119 8 : return;
120 : }
121 :
122 440285 : req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + buflen;
123 :
124 : /* over allocate by a small amount */
125 440285 : req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
126 :
127 440285 : req->out.buffer = talloc_size(req, req->out.allocated);
128 440285 : if (!req->out.buffer) {
129 0 : smbsrv_terminate_connection(req->smb_conn, "allocation failed");
130 0 : return;
131 : }
132 :
133 440285 : flags2 = FLAGS2_LONG_PATH_COMPONENTS |
134 : FLAGS2_EXTENDED_ATTRIBUTES |
135 : FLAGS2_IS_LONG_NAME;
136 : #define _SMB_FLAGS2_ECHOED_FLAGS ( \
137 : FLAGS2_UNICODE_STRINGS | \
138 : FLAGS2_EXTENDED_SECURITY | \
139 : FLAGS2_SMB_SECURITY_SIGNATURES \
140 : )
141 440285 : flags2 |= (req->flags2 & _SMB_FLAGS2_ECHOED_FLAGS);
142 440285 : if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
143 439339 : flags2 |= FLAGS2_32_BIT_ERROR_CODES;
144 : }
145 :
146 440285 : req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
147 440285 : req->out.vwv = req->out.hdr + HDR_VWV;
148 440285 : req->out.wct = wct;
149 440285 : req->out.data = req->out.vwv + VWV(wct) + 2;
150 440285 : req->out.data_size = buflen;
151 440285 : req->out.ptr = req->out.data;
152 :
153 440285 : SIVAL(req->out.hdr, HDR_RCLS, 0);
154 :
155 440285 : SCVAL(req->out.hdr, HDR_WCT, wct);
156 440285 : SSVAL(req->out.vwv, VWV(wct), buflen);
157 :
158 440285 : memcpy(req->out.hdr, "\377SMB", 4);
159 440285 : SCVAL(req->out.hdr,HDR_FLG, FLAG_REPLY | FLAG_CASELESS_PATHNAMES);
160 440285 : SSVAL(req->out.hdr,HDR_FLG2, flags2);
161 440285 : SSVAL(req->out.hdr,HDR_PIDHIGH,0);
162 440285 : memset(req->out.hdr + HDR_SS_FIELD, 0, 10);
163 :
164 440285 : if (req->in.hdr) {
165 : /* copy the cmd, tid, pid, uid and mid from the request */
166 440234 : SCVAL(req->out.hdr,HDR_COM,CVAL(req->in.hdr,HDR_COM));
167 440234 : SSVAL(req->out.hdr,HDR_TID,SVAL(req->in.hdr,HDR_TID));
168 440234 : SSVAL(req->out.hdr,HDR_PID,SVAL(req->in.hdr,HDR_PID));
169 440234 : SSVAL(req->out.hdr,HDR_UID,SVAL(req->in.hdr,HDR_UID));
170 440234 : SSVAL(req->out.hdr,HDR_MID,SVAL(req->in.hdr,HDR_MID));
171 : } else {
172 51 : SCVAL(req->out.hdr,HDR_COM,0);
173 51 : SSVAL(req->out.hdr,HDR_TID,0);
174 51 : SSVAL(req->out.hdr,HDR_PID,0);
175 51 : SSVAL(req->out.hdr,HDR_UID,0);
176 51 : SSVAL(req->out.hdr,HDR_MID,0);
177 : }
178 : }
179 :
180 :
181 : /*
182 : setup a copy of a request, used when the server needs to send
183 : more than one reply for a single request packet
184 : */
185 14 : struct smbsrv_request *smbsrv_setup_secondary_request(struct smbsrv_request *old_req)
186 : {
187 0 : struct smbsrv_request *req;
188 0 : ptrdiff_t diff;
189 :
190 14 : req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));
191 14 : if (req == NULL) {
192 0 : return NULL;
193 : }
194 :
195 14 : req->out.buffer = talloc_memdup(req, req->out.buffer, req->out.allocated);
196 14 : if (req->out.buffer == NULL) {
197 0 : talloc_free(req);
198 0 : return NULL;
199 : }
200 :
201 14 : diff = req->out.buffer - old_req->out.buffer;
202 :
203 14 : req->out.hdr += diff;
204 14 : req->out.vwv += diff;
205 14 : req->out.data += diff;
206 14 : req->out.ptr += diff;
207 :
208 14 : return req;
209 : }
210 :
211 : /*
212 : work out the maximum data size we will allow for this reply, given
213 : the negotiated max_xmit. The basic reply packet must be setup before
214 : this call
215 :
216 : note that this is deliberately a signed integer reply
217 : */
218 193995 : int req_max_data(struct smbsrv_request *req)
219 : {
220 0 : int ret;
221 193995 : ret = req->smb_conn->negotiate.max_send;
222 193995 : ret -= PTR_DIFF(req->out.data, req->out.hdr);
223 193995 : if (ret < 0) ret = 0;
224 193995 : return ret;
225 : }
226 :
227 :
228 : /*
229 : grow the allocation of the data buffer portion of a reply
230 : packet. Note that as this can reallocate the packet buffer this
231 : invalidates any local pointers into the packet.
232 :
233 : To cope with this req->out.ptr is supplied. This will be updated to
234 : point at the same offset into the packet as before this call
235 : */
236 211155 : static void req_grow_allocation(struct smbsrv_request *req, unsigned int new_size)
237 : {
238 0 : int delta;
239 0 : uint8_t *buf2;
240 :
241 211155 : delta = new_size - req->out.data_size;
242 211155 : if (delta + req->out.size <= req->out.allocated) {
243 : /* it fits in the preallocation */
244 183332 : return;
245 : }
246 :
247 : /* we need to realloc */
248 27823 : req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
249 27823 : buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
250 27823 : if (buf2 == NULL) {
251 0 : smb_panic("out of memory in req_grow_allocation");
252 : }
253 :
254 27823 : if (buf2 == req->out.buffer) {
255 : /* the malloc library gave us the same pointer */
256 8088 : return;
257 : }
258 :
259 : /* update the pointers into the packet */
260 19735 : req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
261 19735 : req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
262 19735 : req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
263 19735 : req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
264 :
265 19735 : req->out.buffer = buf2;
266 : }
267 :
268 :
269 : /*
270 : grow the data buffer portion of a reply packet. Note that as this
271 : can reallocate the packet buffer this invalidates any local pointers
272 : into the packet.
273 :
274 : To cope with this req->out.ptr is supplied. This will be updated to
275 : point at the same offset into the packet as before this call
276 : */
277 205693 : void req_grow_data(struct smbsrv_request *req, size_t new_size)
278 : {
279 0 : int delta;
280 :
281 205693 : if (!(req->control_flags & SMBSRV_REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {
282 0 : smb_panic("reply buffer too large!");
283 : }
284 :
285 205693 : req_grow_allocation(req, new_size);
286 :
287 205693 : delta = new_size - req->out.data_size;
288 :
289 205693 : req->out.size += delta;
290 205693 : req->out.data_size += delta;
291 :
292 : /* set the BCC to the new data size */
293 205693 : SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
294 205693 : }
295 :
296 : /*
297 : send a reply and destroy the request buffer
298 :
299 : note that this only looks at req->out.buffer and req->out.size, allowing manually
300 : constructed packets to be sent
301 : */
302 421391 : void smbsrv_send_reply_nosign(struct smbsrv_request *req)
303 : {
304 0 : DATA_BLOB blob;
305 0 : NTSTATUS status;
306 :
307 421391 : if (req->smb_conn->connection->event.fde == NULL) {
308 : /* we are in the process of shutting down this connection */
309 0 : talloc_free(req);
310 0 : return;
311 : }
312 :
313 421391 : if (req->out.size > NBT_HDR_SIZE) {
314 421378 : _smb_setlen_nbt(req->out.buffer, req->out.size - NBT_HDR_SIZE);
315 : }
316 :
317 421391 : blob = data_blob_const(req->out.buffer, req->out.size);
318 421391 : status = packet_send(req->smb_conn->packet, blob);
319 421391 : if (!NT_STATUS_IS_OK(status)) {
320 0 : smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
321 : }
322 421391 : talloc_free(req);
323 : }
324 :
325 : /*
326 : possibly sign a message then send a reply and destroy the request buffer
327 :
328 : note that this only looks at req->out.buffer and req->out.size, allowing manually
329 : constructed packets to be sent
330 : */
331 420436 : void smbsrv_send_reply(struct smbsrv_request *req)
332 : {
333 420436 : if (req->smb_conn->connection->event.fde == NULL) {
334 : /* we are in the process of shutting down this connection */
335 1 : talloc_free(req);
336 1 : return;
337 : }
338 420435 : smbsrv_sign_packet(req);
339 :
340 420435 : smbsrv_send_reply_nosign(req);
341 : }
342 :
343 : /*
344 : setup the header of a reply to include an NTSTATUS code
345 : */
346 144901 : void smbsrv_setup_error(struct smbsrv_request *req, NTSTATUS status)
347 : {
348 144901 : if (!req->smb_conn->config.nt_status_support || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) {
349 : /* convert to DOS error codes */
350 0 : uint8_t eclass;
351 0 : uint32_t ecode;
352 4 : ntstatus_to_dos(status, &eclass, &ecode);
353 4 : SCVAL(req->out.hdr, HDR_RCLS, eclass);
354 4 : SSVAL(req->out.hdr, HDR_ERR, ecode);
355 4 : SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
356 4 : return;
357 : }
358 :
359 144897 : if (NT_STATUS_IS_DOS(status)) {
360 : /* its a encoded DOS error, using the reserved range */
361 65572 : SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status));
362 65572 : SSVAL(req->out.hdr, HDR_ERR, NT_STATUS_DOS_CODE(status));
363 65572 : SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
364 : } else {
365 79325 : SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));
366 79325 : SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);
367 : }
368 : }
369 :
370 : /*
371 : construct and send an error packet, then destroy the request
372 : auto-converts to DOS error format when appropriate
373 : */
374 144745 : void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status)
375 : {
376 144745 : if (req->smb_conn->connection->event.fde == NULL) {
377 : /* the socket has been destroyed - no point trying to send an error! */
378 20 : talloc_free(req);
379 20 : return;
380 : }
381 144725 : smbsrv_setup_reply(req, 0, 0);
382 :
383 : /* error returns never have any data */
384 144725 : req_grow_data(req, 0);
385 :
386 144725 : smbsrv_setup_error(req, status);
387 144725 : smbsrv_send_reply(req);
388 : }
389 :
390 :
391 : /*
392 : push a string into the data portion of the request packet, growing it if necessary
393 : this gets quite tricky - please be very careful to cover all cases when modifying this
394 :
395 : if dest is NULL, then put the string at the end of the data portion of the packet
396 :
397 : if dest_len is -1 then no limit applies
398 : */
399 5349 : size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, size_t flags)
400 : {
401 0 : size_t len;
402 0 : unsigned int grow_size;
403 0 : uint8_t *buf0;
404 5349 : const int max_bytes_per_char = 3;
405 :
406 5349 : if (!(flags & (STR_ASCII|STR_UNICODE))) {
407 4369 : flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
408 : }
409 :
410 5349 : if (dest == NULL) {
411 5349 : dest = req->out.data + req->out.data_size;
412 : }
413 :
414 5349 : if (dest_len != -1) {
415 0 : len = dest_len;
416 : } else {
417 5349 : len = (strlen(str)+2) * max_bytes_per_char;
418 : }
419 :
420 5349 : grow_size = len + PTR_DIFF(dest, req->out.data);
421 5349 : buf0 = req->out.buffer;
422 :
423 5349 : req_grow_allocation(req, grow_size);
424 :
425 5349 : if (buf0 != req->out.buffer) {
426 3593 : dest = req->out.buffer + PTR_DIFF(dest, buf0);
427 : }
428 :
429 5349 : len = push_string(dest, str, len, flags);
430 :
431 5349 : grow_size = len + PTR_DIFF(dest, req->out.data);
432 :
433 5349 : if (grow_size > req->out.data_size) {
434 5349 : req_grow_data(req, grow_size);
435 : }
436 :
437 5349 : return len;
438 : }
439 :
440 : /*
441 : append raw bytes into the data portion of the request packet
442 : return the number of bytes added
443 : */
444 0 : size_t req_append_bytes(struct smbsrv_request *req,
445 : const uint8_t *bytes, size_t byte_len)
446 : {
447 0 : req_grow_allocation(req, byte_len + req->out.data_size);
448 0 : memcpy(req->out.data + req->out.data_size, bytes, byte_len);
449 0 : req_grow_data(req, byte_len + req->out.data_size);
450 0 : return byte_len;
451 : }
452 : /*
453 : append variable block (type 5 buffer) into the data portion of the request packet
454 : return the number of bytes added
455 : */
456 113 : size_t req_append_var_block(struct smbsrv_request *req,
457 : const uint8_t *bytes, uint16_t byte_len)
458 : {
459 113 : req_grow_allocation(req, byte_len + 3 + req->out.data_size);
460 113 : SCVAL(req->out.data + req->out.data_size, 0, 5);
461 113 : SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
462 113 : if (byte_len > 0) {
463 0 : memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
464 : }
465 113 : req_grow_data(req, byte_len + 3 + req->out.data_size);
466 113 : return byte_len + 3;
467 : }
468 : /**
469 : pull a UCS2 string from a request packet, returning a talloced unix string
470 :
471 : the string length is limited by the 3 things:
472 : - the data size in the request (end of packet)
473 : - the passed 'byte_len' if it is not -1
474 : - the end of string (null termination)
475 :
476 : Note that 'byte_len' is the number of bytes in the packet
477 :
478 : on failure zero is returned and *dest is set to NULL, otherwise the number
479 : of bytes consumed in the packet is returned
480 : */
481 166571 : static size_t req_pull_ucs2(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, unsigned int flags)
482 : {
483 166571 : int src_len, src_len2, alignment=0;
484 0 : bool ret;
485 0 : char *dest2;
486 166571 : size_t converted_size = 0;
487 :
488 166571 : if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
489 73337 : src++;
490 73337 : alignment=1;
491 73337 : if (byte_len != -1) {
492 67034 : byte_len--;
493 : }
494 : }
495 :
496 166571 : if (flags & STR_NO_RANGE_CHECK) {
497 19807 : src_len = byte_len;
498 : } else {
499 146764 : src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
500 146764 : if (byte_len != -1 && src_len > byte_len) {
501 66949 : src_len = byte_len;
502 : }
503 : }
504 :
505 166571 : if (src_len < 0) {
506 0 : *dest = NULL;
507 0 : return 0;
508 : }
509 :
510 166571 : src_len2 = utf16_null_terminated_len_n(src, src_len);
511 166571 : if (src_len2 == 0) {
512 138 : *dest = talloc_strdup(bufinfo->mem_ctx, "");
513 138 : return src_len2 + alignment;
514 : }
515 :
516 166433 : ret = convert_string_talloc(bufinfo->mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &converted_size);
517 :
518 166433 : if (!ret) {
519 0 : *dest = NULL;
520 0 : return 0;
521 : }
522 166433 : *dest = dest2;
523 :
524 166433 : return src_len2 + alignment;
525 : }
526 :
527 : /**
528 : pull a ascii string from a request packet, returning a talloced string
529 :
530 : the string length is limited by the 3 things:
531 : - the data size in the request (end of packet)
532 : - the passed 'byte_len' if it is not -1
533 : - the end of string (null termination)
534 :
535 : Note that 'byte_len' is the number of bytes in the packet
536 :
537 : on failure zero is returned and *dest is set to NULL, otherwise the number
538 : of bytes consumed in the packet is returned
539 : */
540 17500 : static size_t req_pull_ascii(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, unsigned int flags)
541 : {
542 0 : int src_len, src_len2;
543 0 : bool ret;
544 0 : char *dest2;
545 17500 : size_t converted_size = 0;
546 :
547 17500 : if (flags & STR_NO_RANGE_CHECK) {
548 0 : src_len = byte_len;
549 : } else {
550 17500 : src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
551 17500 : if (src_len < 0) {
552 0 : *dest = NULL;
553 0 : return 0;
554 : }
555 17500 : if (byte_len != -1 && src_len > byte_len) {
556 0 : src_len = byte_len;
557 : }
558 : }
559 :
560 17500 : src_len2 = strnlen((const char *)src, src_len);
561 17500 : if (src_len2 <= src_len - 1) {
562 : /* include the termination if we didn't reach the end of the packet */
563 17500 : src_len2++;
564 : }
565 :
566 17500 : ret = convert_string_talloc(bufinfo->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &converted_size);
567 :
568 17500 : if (!ret) {
569 0 : *dest = NULL;
570 0 : return 0;
571 : }
572 17500 : *dest = dest2;
573 :
574 17500 : return src_len2;
575 : }
576 :
577 : /**
578 : pull a string from a request packet, returning a talloced string
579 :
580 : the string length is limited by the 3 things:
581 : - the data size in the request (end of packet)
582 : - the passed 'byte_len' if it is not -1
583 : - the end of string (null termination)
584 :
585 : Note that 'byte_len' is the number of bytes in the packet
586 :
587 : on failure zero is returned and *dest is set to NULL, otherwise the number
588 : of bytes consumed in the packet is returned
589 : */
590 184071 : size_t req_pull_string(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, unsigned int flags)
591 : {
592 184071 : if (!(flags & STR_ASCII) &&
593 166587 : (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
594 166571 : return req_pull_ucs2(bufinfo, dest, src, byte_len, flags);
595 : }
596 :
597 17500 : return req_pull_ascii(bufinfo, dest, src, byte_len, flags);
598 : }
599 :
600 :
601 : /**
602 : pull a ASCII4 string buffer from a request packet, returning a talloced string
603 :
604 : an ASCII4 buffer is a null terminated string that has a prefix
605 : of the character 0x4. It tends to be used in older parts of the protocol.
606 :
607 : on failure *dest is set to the zero length string. This seems to
608 : match win2000 behaviour
609 : */
610 94019 : size_t req_pull_ascii4(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, unsigned int flags)
611 : {
612 0 : ssize_t ret;
613 :
614 94019 : if (PTR_DIFF(src, bufinfo->data) + 1 > bufinfo->data_size) {
615 : /* win2000 treats this as the empty string! */
616 2159 : (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
617 2159 : return 0;
618 : }
619 :
620 : /* this consumes the 0x4 byte. We don't check whether the byte
621 : is actually 0x4 or not. This matches win2000 server
622 : behaviour */
623 91860 : src++;
624 :
625 91860 : ret = req_pull_string(bufinfo, dest, src, -1, flags);
626 91860 : if (ret == -1) {
627 0 : (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
628 0 : return 1;
629 : }
630 :
631 91860 : return ret + 1;
632 : }
633 :
634 : /**
635 : pull a DATA_BLOB from a request packet, returning a talloced blob
636 :
637 : return false if any part is outside the data portion of the packet
638 : */
639 78663 : bool req_pull_blob(struct request_bufinfo *bufinfo, const uint8_t *src, int len, DATA_BLOB *blob)
640 : {
641 78663 : if (len != 0 && req_data_oob(bufinfo, src, len)) {
642 0 : return false;
643 : }
644 :
645 78663 : (*blob) = data_blob_talloc(bufinfo->mem_ctx, src, len);
646 :
647 78663 : return true;
648 : }
649 :
650 : /* check that a lump of data in a request is within the bounds of the data section of
651 : the packet */
652 93525 : bool req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
653 : {
654 93525 : if (count == 0) {
655 59 : return false;
656 : }
657 :
658 : /* be careful with wraparound! */
659 93466 : if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
660 93466 : (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
661 93465 : count > bufinfo->data_size ||
662 93465 : (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
663 1 : return true;
664 : }
665 93465 : return false;
666 : }
667 :
668 :
669 : /*
670 : pull an open file handle from a packet, taking account of the chained_fnum
671 : */
672 320796 : static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, unsigned int offset)
673 : {
674 320796 : if (req->chained_fnum != -1) {
675 6 : return req->chained_fnum;
676 : }
677 320790 : return SVAL(base, offset);
678 : }
679 :
680 320796 : struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, unsigned int offset)
681 : {
682 0 : struct smbsrv_handle *handle;
683 320796 : uint16_t fnum = req_fnum(req, base, offset);
684 :
685 320796 : handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time);
686 320796 : if (!handle) {
687 52700 : return NULL;
688 : }
689 :
690 : /*
691 : * For SMB tcons and sessions can be mixed!
692 : * But we need to make sure that file handles
693 : * are only accessed by the opening session!
694 : *
695 : * So check if the handle is valid for the given session!
696 : */
697 268096 : if (handle->session != req->session) {
698 20 : return NULL;
699 : }
700 :
701 268076 : return handle->ntvfs;
702 : }
703 :
704 73587 : void smbsrv_push_fnum(uint8_t *base, unsigned int offset, struct ntvfs_handle *ntvfs)
705 : {
706 73587 : struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data,
707 : struct smbsrv_handle);
708 73587 : SSVAL(base, offset, handle->hid);
709 73587 : }
710 :
711 77470 : NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h)
712 : {
713 77470 : struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
714 : struct smbsrv_request);
715 0 : struct smbsrv_handle *handle;
716 0 : struct ntvfs_handle *h;
717 :
718 77470 : handle = smbsrv_handle_new(req->session, req->tcon, req, req->request_time);
719 77470 : if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES;
720 :
721 77470 : h = talloc_zero(handle, struct ntvfs_handle);
722 77470 : if (!h) goto nomem;
723 :
724 : /*
725 : * note: we don't set handle->ntvfs yet,
726 : * this will be done by smbsrv_handle_make_valid()
727 : * this makes sure the handle is invalid for clients
728 : * until the ntvfs subsystem has made it valid
729 : */
730 77470 : h->ctx = ntvfs->ctx;
731 77470 : h->session_info = ntvfs->session_info;
732 77470 : h->smbpid = ntvfs->smbpid;
733 :
734 77470 : h->frontend_data.private_data = handle;
735 :
736 77470 : *_h = h;
737 77470 : return NT_STATUS_OK;
738 0 : nomem:
739 0 : talloc_free(handle);
740 0 : return NT_STATUS_NO_MEMORY;
741 : }
742 :
743 73536 : NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h)
744 : {
745 73536 : struct smbsrv_tcon *tcon = talloc_get_type(private_data, struct smbsrv_tcon);
746 73536 : struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
747 : struct smbsrv_handle);
748 : /* this tells the frontend that the handle is valid */
749 73536 : handle->ntvfs = h;
750 : /* this moves the smbsrv_request to the smbsrv_tcon memory context */
751 73536 : talloc_steal(tcon, handle);
752 73536 : return NT_STATUS_OK;
753 : }
754 :
755 64062 : void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h)
756 : {
757 64062 : struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
758 : struct smbsrv_handle);
759 64062 : talloc_free(handle);
760 64062 : }
761 :
762 42 : struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key)
763 : {
764 42 : struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
765 : struct smbsrv_request);
766 :
767 42 : if (key->length != 2) return NULL;
768 :
769 42 : return smbsrv_pull_fnum(req, key->data, 0);
770 : }
771 :
772 0 : DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx)
773 : {
774 0 : uint8_t key[2];
775 :
776 0 : smbsrv_push_fnum(key, 0, handle);
777 :
778 0 : return data_blob_talloc(mem_ctx, key, sizeof(key));
779 : }
|