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