idl: rebuild drsuapi.idl
[Samba/aatanasov.git] / source4 / smb_server / smb / request.c
blob6846f80594f937c73b10395e4397953a1fb0786e
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
21 this file implements functions for manipulating the 'struct smbsrv_request' structure in smbd
24 #include "includes.h"
25 #include "smb_server/smb_server.h"
26 #include "smb_server/service_smb_proto.h"
27 #include "smbd/service_stream.h"
28 #include "lib/stream/packet.h"
29 #include "ntvfs/ntvfs.h"
32 /* we over allocate the data buffer to prevent too many realloc calls */
33 #define REQ_OVER_ALLOCATION 0
35 /* setup the bufinfo used for strings and range checking */
36 void smbsrv_setup_bufinfo(struct smbsrv_request *req)
38 req->in.bufinfo.mem_ctx = req;
39 req->in.bufinfo.flags = 0;
40 if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
41 req->in.bufinfo.flags |= BUFINFO_FLAG_UNICODE;
43 req->in.bufinfo.align_base = req->in.buffer;
44 req->in.bufinfo.data = req->in.data;
45 req->in.bufinfo.data_size = req->in.data_size;
49 static int smbsrv_request_destructor(struct smbsrv_request *req)
51 DLIST_REMOVE(req->smb_conn->requests, req);
52 return 0;
55 /****************************************************************************
56 construct a basic request packet, mostly used to construct async packets
57 such as change notify and oplock break requests
58 ****************************************************************************/
59 struct smbsrv_request *smbsrv_init_request(struct smbsrv_connection *smb_conn)
61 struct smbsrv_request *req;
63 req = talloc_zero(smb_conn, struct smbsrv_request);
64 if (!req) {
65 return NULL;
68 /* setup the request context */
69 req->smb_conn = smb_conn;
71 talloc_set_destructor(req, smbsrv_request_destructor);
73 return req;
78 setup a chained reply in req->out with the given word count and initial data buffer size.
80 static void req_setup_chain_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen)
82 uint32_t chain_base_size = req->out.size;
84 /* we need room for the wct value, the words, the buffer length and the buffer */
85 req->out.size += 1 + VWV(wct) + 2 + buflen;
87 /* over allocate by a small amount */
88 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
90 req->out.buffer = talloc_realloc(req, req->out.buffer,
91 uint8_t, req->out.allocated);
92 if (!req->out.buffer) {
93 smbsrv_terminate_connection(req->smb_conn, "allocation failed");
94 return;
97 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
98 req->out.vwv = req->out.buffer + chain_base_size + 1;
99 req->out.wct = wct;
100 req->out.data = req->out.vwv + VWV(wct) + 2;
101 req->out.data_size = buflen;
102 req->out.ptr = req->out.data;
104 SCVAL(req->out.buffer, chain_base_size, wct);
105 SSVAL(req->out.vwv, VWV(wct), buflen);
110 setup a reply in req->out with the given word count and initial data buffer size.
111 the caller will then fill in the command words and data before calling req_send_reply() to
112 send the reply on its way
114 void smbsrv_setup_reply(struct smbsrv_request *req, uint_t wct, size_t buflen)
116 uint16_t flags2;
118 if (req->chain_count != 0) {
119 req_setup_chain_reply(req, wct, buflen);
120 return;
123 req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + buflen;
125 /* over allocate by a small amount */
126 req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
128 req->out.buffer = talloc_size(req, req->out.allocated);
129 if (!req->out.buffer) {
130 smbsrv_terminate_connection(req->smb_conn, "allocation failed");
131 return;
134 flags2 = FLAGS2_LONG_PATH_COMPONENTS |
135 FLAGS2_EXTENDED_ATTRIBUTES |
136 FLAGS2_IS_LONG_NAME;
137 #define _SMB_FLAGS2_ECHOED_FLAGS ( \
138 FLAGS2_UNICODE_STRINGS | \
139 FLAGS2_EXTENDED_SECURITY | \
140 FLAGS2_SMB_SECURITY_SIGNATURES \
142 flags2 |= (req->flags2 & _SMB_FLAGS2_ECHOED_FLAGS);
143 if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
144 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
147 req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
148 req->out.vwv = req->out.hdr + HDR_VWV;
149 req->out.wct = wct;
150 req->out.data = req->out.vwv + VWV(wct) + 2;
151 req->out.data_size = buflen;
152 req->out.ptr = req->out.data;
154 SIVAL(req->out.hdr, HDR_RCLS, 0);
156 SCVAL(req->out.hdr, HDR_WCT, wct);
157 SSVAL(req->out.vwv, VWV(wct), buflen);
159 memcpy(req->out.hdr, "\377SMB", 4);
160 SCVAL(req->out.hdr,HDR_FLG, FLAG_REPLY | FLAG_CASELESS_PATHNAMES);
161 SSVAL(req->out.hdr,HDR_FLG2, flags2);
162 SSVAL(req->out.hdr,HDR_PIDHIGH,0);
163 memset(req->out.hdr + HDR_SS_FIELD, 0, 10);
165 if (req->in.hdr) {
166 /* copy the cmd, tid, pid, uid and mid from the request */
167 SCVAL(req->out.hdr,HDR_COM,CVAL(req->in.hdr,HDR_COM));
168 SSVAL(req->out.hdr,HDR_TID,SVAL(req->in.hdr,HDR_TID));
169 SSVAL(req->out.hdr,HDR_PID,SVAL(req->in.hdr,HDR_PID));
170 SSVAL(req->out.hdr,HDR_UID,SVAL(req->in.hdr,HDR_UID));
171 SSVAL(req->out.hdr,HDR_MID,SVAL(req->in.hdr,HDR_MID));
172 } else {
173 SCVAL(req->out.hdr,HDR_COM,0);
174 SSVAL(req->out.hdr,HDR_TID,0);
175 SSVAL(req->out.hdr,HDR_PID,0);
176 SSVAL(req->out.hdr,HDR_UID,0);
177 SSVAL(req->out.hdr,HDR_MID,0);
183 setup a copy of a request, used when the server needs to send
184 more than one reply for a single request packet
186 struct smbsrv_request *smbsrv_setup_secondary_request(struct smbsrv_request *old_req)
188 struct smbsrv_request *req;
189 ptrdiff_t diff;
191 req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));
192 if (req == NULL) {
193 return NULL;
196 req->out.buffer = talloc_memdup(req, req->out.buffer, req->out.allocated);
197 if (req->out.buffer == NULL) {
198 talloc_free(req);
199 return NULL;
202 diff = req->out.buffer - old_req->out.buffer;
204 req->out.hdr += diff;
205 req->out.vwv += diff;
206 req->out.data += diff;
207 req->out.ptr += diff;
209 return req;
213 work out the maximum data size we will allow for this reply, given
214 the negotiated max_xmit. The basic reply packet must be setup before
215 this call
217 note that this is deliberately a signed integer reply
219 int req_max_data(struct smbsrv_request *req)
221 int ret;
222 ret = req->smb_conn->negotiate.max_send;
223 ret -= PTR_DIFF(req->out.data, req->out.hdr);
224 if (ret < 0) ret = 0;
225 return ret;
230 grow the allocation of the data buffer portion of a reply
231 packet. Note that as this can reallocate the packet buffer this
232 invalidates any local pointers into the packet.
234 To cope with this req->out.ptr is supplied. This will be updated to
235 point at the same offset into the packet as before this call
237 static void req_grow_allocation(struct smbsrv_request *req, uint_t new_size)
239 int delta;
240 uint8_t *buf2;
242 delta = new_size - req->out.data_size;
243 if (delta + req->out.size <= req->out.allocated) {
244 /* it fits in the preallocation */
245 return;
248 /* we need to realloc */
249 req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
250 buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
251 if (buf2 == NULL) {
252 smb_panic("out of memory in req_grow_allocation");
255 if (buf2 == req->out.buffer) {
256 /* the malloc library gave us the same pointer */
257 return;
260 /* update the pointers into the packet */
261 req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
262 req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
263 req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
264 req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
266 req->out.buffer = buf2;
271 grow the data buffer portion of a reply packet. Note that as this
272 can reallocate the packet buffer this invalidates any local pointers
273 into the packet.
275 To cope with this req->out.ptr is supplied. This will be updated to
276 point at the same offset into the packet as before this call
278 void req_grow_data(struct smbsrv_request *req, size_t new_size)
280 int delta;
282 if (!(req->control_flags & SMBSRV_REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {
283 smb_panic("reply buffer too large!");
286 req_grow_allocation(req, new_size);
288 delta = new_size - req->out.data_size;
290 req->out.size += delta;
291 req->out.data_size += delta;
293 /* set the BCC to the new data size */
294 SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
298 send a reply and destroy the request buffer
300 note that this only looks at req->out.buffer and req->out.size, allowing manually
301 constructed packets to be sent
303 void smbsrv_send_reply_nosign(struct smbsrv_request *req)
305 DATA_BLOB blob;
306 NTSTATUS status;
308 if (req->smb_conn->connection->event.fde == NULL) {
309 /* we are in the process of shutting down this connection */
310 talloc_free(req);
311 return;
314 if (req->out.size > NBT_HDR_SIZE) {
315 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
318 blob = data_blob_const(req->out.buffer, req->out.size);
319 status = packet_send(req->smb_conn->packet, blob);
320 if (!NT_STATUS_IS_OK(status)) {
321 smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
323 talloc_free(req);
327 possibly sign a message then send a reply and destroy the request buffer
329 note that this only looks at req->out.buffer and req->out.size, allowing manually
330 constructed packets to be sent
332 void smbsrv_send_reply(struct smbsrv_request *req)
334 if (req->smb_conn->connection->event.fde == NULL) {
335 /* we are in the process of shutting down this connection */
336 talloc_free(req);
337 return;
339 smbsrv_sign_packet(req);
341 smbsrv_send_reply_nosign(req);
345 setup the header of a reply to include an NTSTATUS code
347 void smbsrv_setup_error(struct smbsrv_request *req, NTSTATUS status)
349 if (!req->smb_conn->config.nt_status_support || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) {
350 /* convert to DOS error codes */
351 uint8_t eclass;
352 uint32_t ecode;
353 ntstatus_to_dos(status, &eclass, &ecode);
354 SCVAL(req->out.hdr, HDR_RCLS, eclass);
355 SSVAL(req->out.hdr, HDR_ERR, ecode);
356 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
357 return;
360 if (NT_STATUS_IS_DOS(status)) {
361 /* its a encoded DOS error, using the reserved range */
362 SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status));
363 SSVAL(req->out.hdr, HDR_ERR, NT_STATUS_DOS_CODE(status));
364 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
365 } else {
366 SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));
367 SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);
372 construct and send an error packet, then destroy the request
373 auto-converts to DOS error format when appropriate
375 void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status)
377 if (req->smb_conn->connection->event.fde == NULL) {
378 /* the socket has been destroyed - no point trying to send an error! */
379 talloc_free(req);
380 return;
382 smbsrv_setup_reply(req, 0, 0);
384 /* error returns never have any data */
385 req_grow_data(req, 0);
387 smbsrv_setup_error(req, status);
388 smbsrv_send_reply(req);
393 push a string into the data portion of the request packet, growing it if necessary
394 this gets quite tricky - please be very careful to cover all cases when modifying this
396 if dest is NULL, then put the string at the end of the data portion of the packet
398 if dest_len is -1 then no limit applies
400 size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, size_t flags)
402 size_t len;
403 uint_t grow_size;
404 uint8_t *buf0;
405 const int max_bytes_per_char = 3;
407 if (!(flags & (STR_ASCII|STR_UNICODE))) {
408 flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
411 if (dest == NULL) {
412 dest = req->out.data + req->out.data_size;
415 if (dest_len != -1) {
416 len = dest_len;
417 } else {
418 len = (strlen(str)+2) * max_bytes_per_char;
421 grow_size = len + PTR_DIFF(dest, req->out.data);
422 buf0 = req->out.buffer;
424 req_grow_allocation(req, grow_size);
426 if (buf0 != req->out.buffer) {
427 dest = req->out.buffer + PTR_DIFF(dest, buf0);
430 len = push_string(dest, str, len, flags);
432 grow_size = len + PTR_DIFF(dest, req->out.data);
434 if (grow_size > req->out.data_size) {
435 req_grow_data(req, grow_size);
438 return len;
442 append raw bytes into the data portion of the request packet
443 return the number of bytes added
445 size_t req_append_bytes(struct smbsrv_request *req,
446 const uint8_t *bytes, size_t byte_len)
448 req_grow_allocation(req, byte_len + req->out.data_size);
449 memcpy(req->out.data + req->out.data_size, bytes, byte_len);
450 req_grow_data(req, byte_len + req->out.data_size);
451 return byte_len;
454 append variable block (type 5 buffer) into the data portion of the request packet
455 return the number of bytes added
457 size_t req_append_var_block(struct smbsrv_request *req,
458 const uint8_t *bytes, uint16_t byte_len)
460 req_grow_allocation(req, byte_len + 3 + req->out.data_size);
461 SCVAL(req->out.data + req->out.data_size, 0, 5);
462 SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
463 if (byte_len > 0) {
464 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
466 req_grow_data(req, byte_len + 3 + req->out.data_size);
467 return byte_len + 3;
470 pull a UCS2 string from a request packet, returning a talloced unix string
472 the string length is limited by the 3 things:
473 - the data size in the request (end of packet)
474 - the passed 'byte_len' if it is not -1
475 - the end of string (null termination)
477 Note that 'byte_len' is the number of bytes in the packet
479 on failure zero is returned and *dest is set to NULL, otherwise the number
480 of bytes consumed in the packet is returned
482 static size_t req_pull_ucs2(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
484 int src_len, src_len2, alignment=0;
485 bool ret;
486 char *dest2;
488 if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
489 src++;
490 alignment=1;
491 if (byte_len != -1) {
492 byte_len--;
496 if (flags & STR_NO_RANGE_CHECK) {
497 src_len = byte_len;
498 } else {
499 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
500 if (byte_len != -1 && src_len > byte_len) {
501 src_len = byte_len;
505 if (src_len < 0) {
506 *dest = NULL;
507 return 0;
510 src_len2 = utf16_len_n(src, src_len);
511 if (src_len2 == 0) {
512 *dest = talloc_strdup(bufinfo->mem_ctx, "");
513 return src_len2 + alignment;
516 ret = convert_string_talloc(bufinfo->mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
518 if (!ret) {
519 *dest = NULL;
520 return 0;
522 *dest = dest2;
524 return src_len2 + alignment;
528 pull a ascii string from a request packet, returning a talloced string
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)
535 Note that 'byte_len' is the number of bytes in the packet
537 on failure zero is returned and *dest is set to NULL, otherwise the number
538 of bytes consumed in the packet is returned
540 static size_t req_pull_ascii(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
542 int src_len, src_len2;
543 bool ret;
544 char *dest2;
546 if (flags & STR_NO_RANGE_CHECK) {
547 src_len = byte_len;
548 } else {
549 src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
550 if (src_len < 0) {
551 *dest = NULL;
552 return 0;
554 if (byte_len != -1 && src_len > byte_len) {
555 src_len = byte_len;
559 src_len2 = strnlen((const char *)src, src_len);
560 if (src_len2 <= src_len - 1) {
561 /* include the termination if we didn't reach the end of the packet */
562 src_len2++;
565 ret = convert_string_talloc(bufinfo->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
567 if (!ret) {
568 *dest = NULL;
569 return 0;
571 *dest = dest2;
573 return src_len2;
577 pull a string from a request packet, returning a talloced string
579 the string length is limited by the 3 things:
580 - the data size in the request (end of packet)
581 - the passed 'byte_len' if it is not -1
582 - the end of string (null termination)
584 Note that 'byte_len' is the number of bytes in the packet
586 on failure zero is returned and *dest is set to NULL, otherwise the number
587 of bytes consumed in the packet is returned
589 size_t req_pull_string(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
591 if (!(flags & STR_ASCII) &&
592 (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
593 return req_pull_ucs2(bufinfo, dest, src, byte_len, flags);
596 return req_pull_ascii(bufinfo, dest, src, byte_len, flags);
601 pull a ASCII4 string buffer from a request packet, returning a talloced string
603 an ASCII4 buffer is a null terminated string that has a prefix
604 of the character 0x4. It tends to be used in older parts of the protocol.
606 on failure *dest is set to the zero length string. This seems to
607 match win2000 behaviour
609 size_t req_pull_ascii4(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, uint_t flags)
611 ssize_t ret;
613 if (PTR_DIFF(src, bufinfo->data) + 1 > bufinfo->data_size) {
614 /* win2000 treats this as the empty string! */
615 (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
616 return 0;
619 /* this consumes the 0x4 byte. We don't check whether the byte
620 is actually 0x4 or not. This matches win2000 server
621 behaviour */
622 src++;
624 ret = req_pull_string(bufinfo, dest, src, -1, flags);
625 if (ret == -1) {
626 (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
627 return 1;
630 return ret + 1;
634 pull a DATA_BLOB from a request packet, returning a talloced blob
636 return false if any part is outside the data portion of the packet
638 bool req_pull_blob(struct request_bufinfo *bufinfo, const uint8_t *src, int len, DATA_BLOB *blob)
640 if (len != 0 && req_data_oob(bufinfo, src, len)) {
641 return false;
644 (*blob) = data_blob_talloc(bufinfo->mem_ctx, src, len);
646 return true;
649 /* check that a lump of data in a request is within the bounds of the data section of
650 the packet */
651 bool req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
653 if (count == 0) {
654 return false;
657 /* be careful with wraparound! */
658 if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
659 (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
660 count > bufinfo->data_size ||
661 (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
662 return true;
664 return false;
669 pull an open file handle from a packet, taking account of the chained_fnum
671 static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
673 if (req->chained_fnum != -1) {
674 return req->chained_fnum;
676 return SVAL(base, offset);
679 struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
681 struct smbsrv_handle *handle;
682 uint16_t fnum = req_fnum(req, base, offset);
684 handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time);
685 if (!handle) {
686 return NULL;
690 * For SMB tcons and sessions can be mixed!
691 * But we need to make sure that file handles
692 * are only accessed by the opening session!
694 * So check if the handle is valid for the given session!
696 if (handle->session != req->session) {
697 return NULL;
700 return handle->ntvfs;
703 void smbsrv_push_fnum(uint8_t *base, uint_t offset, struct ntvfs_handle *ntvfs)
705 struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data,
706 struct smbsrv_handle);
707 SSVAL(base, offset, handle->hid);
710 NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h)
712 struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
713 struct smbsrv_request);
714 struct smbsrv_handle *handle;
715 struct ntvfs_handle *h;
717 handle = smbsrv_handle_new(req->session, req->tcon, req, req->request_time);
718 if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES;
720 h = talloc_zero(handle, struct ntvfs_handle);
721 if (!h) goto nomem;
724 * note: we don't set handle->ntvfs yet,
725 * this will be done by smbsrv_handle_make_valid()
726 * this makes sure the handle is invalid for clients
727 * until the ntvfs subsystem has made it valid
729 h->ctx = ntvfs->ctx;
730 h->session_info = ntvfs->session_info;
731 h->smbpid = ntvfs->smbpid;
733 h->frontend_data.private_data = handle;
735 *_h = h;
736 return NT_STATUS_OK;
737 nomem:
738 talloc_free(handle);
739 return NT_STATUS_NO_MEMORY;
742 NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h)
744 struct smbsrv_tcon *tcon = talloc_get_type(private_data, struct smbsrv_tcon);
745 struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
746 struct smbsrv_handle);
747 /* this tells the frontend that the handle is valid */
748 handle->ntvfs = h;
749 /* this moves the smbsrv_request to the smbsrv_tcon memory context */
750 talloc_steal(tcon, handle);
751 return NT_STATUS_OK;
754 void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h)
756 struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
757 struct smbsrv_handle);
758 talloc_free(handle);
761 struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key)
763 struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
764 struct smbsrv_request);
766 if (key->length != 2) return NULL;
768 return smbsrv_pull_fnum(req, key->data, 0);
771 DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx)
773 uint8_t key[2];
775 smbsrv_push_fnum(key, 0, handle);
777 return data_blob_talloc(mem_ctx, key, sizeof(key));