root/source4/smb_server/smb/request.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smbsrv_setup_bufinfo
  2. smbsrv_request_destructor
  3. smbsrv_init_request
  4. req_setup_chain_reply
  5. smbsrv_setup_reply
  6. smbsrv_setup_secondary_request
  7. req_max_data
  8. req_grow_allocation
  9. req_grow_data
  10. smbsrv_send_reply_nosign
  11. smbsrv_send_reply
  12. smbsrv_setup_error
  13. smbsrv_send_error
  14. req_push_str
  15. req_append_bytes
  16. req_append_var_block
  17. req_pull_ucs2
  18. req_pull_ascii
  19. req_pull_string
  20. req_pull_ascii4
  21. req_pull_blob
  22. req_data_oob
  23. req_fnum
  24. smbsrv_pull_fnum
  25. smbsrv_push_fnum
  26. smbsrv_handle_create_new
  27. smbsrv_handle_make_valid
  28. smbsrv_handle_destroy
  29. smbsrv_handle_search_by_wire_key
  30. smbsrv_handle_get_wire_key

   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 "smb_server/service_smb_proto.h"
  27 #include "smbd/service_stream.h"
  28 #include "lib/stream/packet.h"
  29 #include "ntvfs/ntvfs.h"
  30 
  31 
  32 /* we over allocate the data buffer to prevent too many realloc calls */
  33 #define REQ_OVER_ALLOCATION 0
  34 
  35 /* setup the bufinfo used for strings and range checking */
  36 void smbsrv_setup_bufinfo(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  37 {
  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;
  42         }
  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;
  46 }
  47 
  48 
  49 static int smbsrv_request_destructor(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         DLIST_REMOVE(req->smb_conn->requests, req);
  52         return 0;
  53 }
  54 
  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)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         struct smbsrv_request *req;
  62 
  63         req = talloc_zero(smb_conn, struct smbsrv_request);
  64         if (!req) {
  65                 return NULL;
  66         }
  67 
  68         /* setup the request context */
  69         req->smb_conn = smb_conn;
  70 
  71         talloc_set_destructor(req, smbsrv_request_destructor);
  72 
  73         return req;
  74 }
  75 
  76 
  77 /*
  78   setup a chained reply in req->out with the given word count and initial data buffer size. 
  79 */
  80 static void req_setup_chain_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82         uint32_t chain_base_size = req->out.size;
  83 
  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;
  86 
  87         /* over allocate by a small amount */
  88         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
  89 
  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;
  95         }
  96 
  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;
 103 
 104         SCVAL(req->out.buffer, chain_base_size, wct);
 105         SSVAL(req->out.vwv, VWV(wct), buflen);
 106 }
 107 
 108 
 109 /*
 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
 113 */
 114 void smbsrv_setup_reply(struct smbsrv_request *req, uint_t wct, size_t buflen)
     /* [<][>][^][v][top][bottom][index][help] */
 115 {
 116         uint16_t flags2;
 117 
 118         if (req->chain_count != 0) {
 119                 req_setup_chain_reply(req, wct, buflen);
 120                 return;
 121         }
 122 
 123         req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + buflen;
 124 
 125         /* over allocate by a small amount */
 126         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
 127 
 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;
 132         }
 133 
 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 \
 141 )
 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;
 145         }
 146 
 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;
 153 
 154         SIVAL(req->out.hdr, HDR_RCLS, 0);
 155 
 156         SCVAL(req->out.hdr, HDR_WCT, wct);
 157         SSVAL(req->out.vwv, VWV(wct), buflen);
 158 
 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);
 164 
 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);
 178         }
 179 }
 180 
 181 
 182 /*
 183   setup a copy of a request, used when the server needs to send
 184   more than one reply for a single request packet
 185 */
 186 struct smbsrv_request *smbsrv_setup_secondary_request(struct smbsrv_request *old_req)
     /* [<][>][^][v][top][bottom][index][help] */
 187 {
 188         struct smbsrv_request *req;
 189         ptrdiff_t diff;
 190 
 191         req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));
 192         if (req == NULL) {
 193                 return NULL;
 194         }
 195 
 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;
 200         }
 201 
 202         diff = req->out.buffer - old_req->out.buffer;
 203 
 204         req->out.hdr  += diff;
 205         req->out.vwv  += diff;
 206         req->out.data += diff;
 207         req->out.ptr  += diff;
 208 
 209         return req;
 210 }
 211 
 212 /*
 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
 216 
 217   note that this is deliberately a signed integer reply
 218 */
 219 int req_max_data(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 220 {
 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;
 226 }
 227 
 228 
 229 /*
 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.
 233 
 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
 236 */
 237 static void req_grow_allocation(struct smbsrv_request *req, uint_t new_size)
     /* [<][>][^][v][top][bottom][index][help] */
 238 {
 239         int delta;
 240         uint8_t *buf2;
 241 
 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;
 246         }
 247 
 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");
 253         }
 254 
 255         if (buf2 == req->out.buffer) {
 256                 /* the malloc library gave us the same pointer */
 257                 return;
 258         }
 259         
 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);
 265 
 266         req->out.buffer = buf2;
 267 }
 268 
 269 
 270 /*
 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. 
 274 
 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
 277 */
 278 void req_grow_data(struct smbsrv_request *req, size_t new_size)
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280         int delta;
 281 
 282         if (!(req->control_flags & SMBSRV_REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {
 283                 smb_panic("reply buffer too large!");
 284         }
 285 
 286         req_grow_allocation(req, new_size);
 287 
 288         delta = new_size - req->out.data_size;
 289 
 290         req->out.size += delta;
 291         req->out.data_size += delta;
 292 
 293         /* set the BCC to the new data size */
 294         SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
 295 }
 296 
 297 /*
 298   send a reply and destroy the request buffer
 299 
 300   note that this only looks at req->out.buffer and req->out.size, allowing manually 
 301   constructed packets to be sent
 302 */
 303 void smbsrv_send_reply_nosign(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 304 {
 305         DATA_BLOB blob;
 306         NTSTATUS status;
 307 
 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;
 312         }
 313 
 314         if (req->out.size > NBT_HDR_SIZE) {
 315                 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
 316         }
 317 
 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));
 322         }
 323         talloc_free(req);
 324 }
 325 
 326 /*
 327   possibly sign a message then send a reply and destroy the request buffer
 328 
 329   note that this only looks at req->out.buffer and req->out.size, allowing manually 
 330   constructed packets to be sent
 331 */
 332 void smbsrv_send_reply(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 333 {
 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;
 338         }
 339         smbsrv_sign_packet(req);
 340 
 341         smbsrv_send_reply_nosign(req);
 342 }
 343 
 344 /* 
 345    setup the header of a reply to include an NTSTATUS code
 346 */
 347 void smbsrv_setup_error(struct smbsrv_request *req, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 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;
 358         }
 359 
 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);
 368         }
 369 }
 370 
 371 /* 
 372    construct and send an error packet, then destroy the request 
 373    auto-converts to DOS error format when appropriate
 374 */
 375 void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
 376 {
 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;
 381         }
 382         smbsrv_setup_reply(req, 0, 0);
 383 
 384         /* error returns never have any data */
 385         req_grow_data(req, 0);
 386 
 387         smbsrv_setup_error(req, status);
 388         smbsrv_send_reply(req);
 389 }
 390 
 391 
 392 /*
 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
 395 
 396   if dest is NULL, then put the string at the end of the data portion of the packet
 397 
 398   if dest_len is -1 then no limit applies
 399 */
 400 size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, size_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 401 {
 402         size_t len;
 403         uint_t grow_size;
 404         uint8_t *buf0;
 405         const int max_bytes_per_char = 3;
 406 
 407         if (!(flags & (STR_ASCII|STR_UNICODE))) {
 408                 flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
 409         }
 410 
 411         if (dest == NULL) {
 412                 dest = req->out.data + req->out.data_size;
 413         }
 414 
 415         if (dest_len != -1) {
 416                 len = dest_len;
 417         } else {
 418                 len = (strlen(str)+2) * max_bytes_per_char;
 419         }
 420 
 421         grow_size = len + PTR_DIFF(dest, req->out.data);
 422         buf0 = req->out.buffer;
 423 
 424         req_grow_allocation(req, grow_size);
 425 
 426         if (buf0 != req->out.buffer) {
 427                 dest = req->out.buffer + PTR_DIFF(dest, buf0);
 428         }
 429 
 430         len = push_string(dest, str, len, flags);
 431 
 432         grow_size = len + PTR_DIFF(dest, req->out.data);
 433 
 434         if (grow_size > req->out.data_size) {
 435                 req_grow_data(req, grow_size);
 436         }
 437 
 438         return len;
 439 }
 440 
 441 /*
 442   append raw bytes into the data portion of the request packet
 443   return the number of bytes added
 444 */
 445 size_t req_append_bytes(struct smbsrv_request *req, 
     /* [<][>][^][v][top][bottom][index][help] */
 446                         const uint8_t *bytes, size_t byte_len)
 447 {
 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;
 452 }
 453 /*
 454   append variable block (type 5 buffer) into the data portion of the request packet
 455   return the number of bytes added
 456 */
 457 size_t req_append_var_block(struct smbsrv_request *req, 
     /* [<][>][^][v][top][bottom][index][help] */
 458                 const uint8_t *bytes, uint16_t byte_len)
 459 {
 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);
 465         }
 466         req_grow_data(req, byte_len + 3 + req->out.data_size);
 467         return byte_len + 3;
 468 }
 469 /**
 470   pull a UCS2 string from a request packet, returning a talloced unix string
 471 
 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)
 476 
 477   Note that 'byte_len' is the number of bytes in the packet
 478 
 479   on failure zero is returned and *dest is set to NULL, otherwise the number
 480   of bytes consumed in the packet is returned
 481 */
 482 static size_t req_pull_ucs2(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 483 {
 484         int src_len, src_len2, alignment=0;
 485         bool ret;
 486         char *dest2;
 487 
 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--;
 493                 }
 494         }
 495 
 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;
 502                 }
 503         }
 504 
 505         if (src_len < 0) {
 506                 *dest = NULL;
 507                 return 0;
 508         }
 509         
 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;
 514         }
 515 
 516         ret = convert_string_talloc(bufinfo->mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
 517 
 518         if (!ret) {
 519                 *dest = NULL;
 520                 return 0;
 521         }
 522         *dest = dest2;
 523 
 524         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 static size_t req_pull_ascii(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 541 {
 542         int src_len, src_len2;
 543         bool ret;
 544         char *dest2;
 545 
 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;
 553                 }
 554                 if (byte_len != -1 && src_len > byte_len) {
 555                         src_len = byte_len;
 556                 }
 557         }
 558 
 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++;
 563         }
 564 
 565         ret = convert_string_talloc(bufinfo->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
 566 
 567         if (!ret) {
 568                 *dest = NULL;
 569                 return 0;
 570         }
 571         *dest = dest2;
 572 
 573         return src_len2;
 574 }
 575 
 576 /**
 577   pull a string from a request packet, returning a talloced string
 578 
 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)
 583 
 584   Note that 'byte_len' is the number of bytes in the packet
 585 
 586   on failure zero is returned and *dest is set to NULL, otherwise the number
 587   of bytes consumed in the packet is returned
 588 */
 589 size_t req_pull_string(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 590 {
 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);
 594         }
 595 
 596         return req_pull_ascii(bufinfo, dest, src, byte_len, flags);
 597 }
 598 
 599 
 600 /**
 601   pull a ASCII4 string buffer from a request packet, returning a talloced string
 602   
 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.
 605 
 606   on failure *dest is set to the zero length string. This seems to
 607   match win2000 behaviour
 608 */
 609 size_t req_pull_ascii4(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 610 {
 611         ssize_t ret;
 612 
 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;
 617         }
 618 
 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++;
 623 
 624         ret = req_pull_string(bufinfo, dest, src, -1, flags);
 625         if (ret == -1) {
 626                 (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
 627                 return 1;
 628         }
 629         
 630         return ret + 1;
 631 }
 632 
 633 /**
 634   pull a DATA_BLOB from a request packet, returning a talloced blob
 635 
 636   return false if any part is outside the data portion of the packet
 637 */
 638 bool req_pull_blob(struct request_bufinfo *bufinfo, const uint8_t *src, int len, DATA_BLOB *blob)
     /* [<][>][^][v][top][bottom][index][help] */
 639 {
 640         if (len != 0 && req_data_oob(bufinfo, src, len)) {
 641                 return false;
 642         }
 643 
 644         (*blob) = data_blob_talloc(bufinfo->mem_ctx, src, len);
 645 
 646         return true;
 647 }
 648 
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 652 {
 653         if (count == 0) {
 654                 return false;
 655         }
 656         
 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;
 663         }
 664         return false;
 665 }
 666 
 667 
 668 /* 
 669    pull an open file handle from a packet, taking account of the chained_fnum
 670 */
 671 static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
     /* [<][>][^][v][top][bottom][index][help] */
 672 {
 673         if (req->chained_fnum != -1) {
 674                 return req->chained_fnum;
 675         }
 676         return SVAL(base, offset);
 677 }
 678 
 679 struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
     /* [<][>][^][v][top][bottom][index][help] */
 680 {
 681         struct smbsrv_handle *handle;
 682         uint16_t fnum = req_fnum(req, base, offset);
 683 
 684         handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time);
 685         if (!handle) {
 686                 return NULL;
 687         }
 688 
 689         /*
 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!
 693          *
 694          * So check if the handle is valid for the given session!
 695          */
 696         if (handle->session != req->session) {
 697                 return NULL;
 698         }
 699 
 700         return handle->ntvfs;
 701 }
 702 
 703 void smbsrv_push_fnum(uint8_t *base, uint_t offset, struct ntvfs_handle *ntvfs)
     /* [<][>][^][v][top][bottom][index][help] */
 704 {
 705         struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data,
 706                                        struct smbsrv_handle);
 707         SSVAL(base, offset, handle->hid);
 708 }
 709 
 710 NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h)
     /* [<][>][^][v][top][bottom][index][help] */
 711 {
 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;
 716 
 717         handle = smbsrv_handle_new(req->session, req->tcon, req, req->request_time);
 718         if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES;
 719 
 720         h = talloc_zero(handle, struct ntvfs_handle);
 721         if (!h) goto nomem;
 722 
 723         /* 
 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
 728          */
 729         h->ctx          = ntvfs->ctx;
 730         h->session_info = ntvfs->session_info;
 731         h->smbpid       = ntvfs->smbpid;
 732 
 733         h->frontend_data.private_data = handle;
 734 
 735         *_h = h;
 736         return NT_STATUS_OK;
 737 nomem:
 738         talloc_free(handle);
 739         return NT_STATUS_NO_MEMORY;
 740 }
 741 
 742 NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h)
     /* [<][>][^][v][top][bottom][index][help] */
 743 {
 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;
 752 }
 753 
 754 void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h)
     /* [<][>][^][v][top][bottom][index][help] */
 755 {
 756         struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
 757                                                        struct smbsrv_handle);
 758         talloc_free(handle);
 759 }
 760 
 761 struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key)
     /* [<][>][^][v][top][bottom][index][help] */
 762 {
 763         struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
 764                                      struct smbsrv_request);
 765 
 766         if (key->length != 2) return NULL;
 767 
 768         return smbsrv_pull_fnum(req, key->data, 0);
 769 }
 770 
 771 DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 772 {
 773         uint8_t key[2];
 774 
 775         smbsrv_push_fnum(key, 0, handle);
 776 
 777         return data_blob_talloc(mem_ctx, key, sizeof(key));
 778 }

/* [<][>][^][v][top][bottom][index][help] */