root/source4/libcli/raw/rawrequest.c

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

DEFINITIONS

This source file includes following definitions.
  1. smb_setup_bufinfo
  2. smbcli_request_destroy
  3. smbcli_request_setup_nonsmb
  4. smbcli_request_setup_transport
  5. smbcli_request_setup_session
  6. smbcli_request_setup
  7. smbcli_req_grow_allocation
  8. smbcli_req_grow_data
  9. smbcli_chained_request_setup
  10. smbcli_chained_advance
  11. smbcli_request_send
  12. smbcli_request_receive
  13. smbcli_handle_oplock_break
  14. smbcli_request_simple_recv
  15. smbcli_request_is_error
  16. smbcli_req_append_string
  17. smbcli_req_append_string_len
  18. smbcli_req_append_ascii4
  19. smbcli_req_append_blob
  20. smbcli_req_append_bytes
  21. smbcli_req_append_var_block
  22. smbcli_req_pull_ucs2
  23. smbcli_req_pull_ascii
  24. smbcli_req_pull_string
  25. smbcli_req_pull_blob
  26. smbcli_req_data_oob
  27. smbcli_raw_pull_data
  28. smbcli_push_nttime
  29. smbcli_pull_nttime
  30. smbcli_blob_pull_ucs2
  31. smbcli_blob_pull_ascii
  32. smbcli_blob_pull_string
  33. smbcli_blob_pull_unix_string
  34. smbcli_blob_append_string
  35. smbcli_pull_guid
  36. smbcli_push_guid

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    
   4    Copyright (C) Andrew Tridgell  2003
   5    Copyright (C) James Myers 2003 <myersjj@samba.org>
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 /*
  22   this file implements functions for manipulating the 'struct smbcli_request' structure in libsmb
  23 */
  24 
  25 #include "includes.h"
  26 #include "libcli/raw/libcliraw.h"
  27 #include "libcli/raw/raw_proto.h"
  28 #include "../lib/util/dlinklist.h"
  29 #include "lib/events/events.h"
  30 #include "librpc/ndr/libndr.h"
  31 #include "librpc/gen_ndr/ndr_misc.h"
  32 
  33 /* we over allocate the data buffer to prevent too many realloc calls */
  34 #define REQ_OVER_ALLOCATION 0
  35 
  36 /* assume that a character will not consume more than 3 bytes per char */
  37 #define MAX_BYTES_PER_CHAR 3
  38 
  39 /* setup the bufinfo used for strings and range checking */
  40 void smb_setup_bufinfo(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42         req->in.bufinfo.mem_ctx    = req;
  43         req->in.bufinfo.flags      = 0;
  44         if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
  45                 req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
  46         }
  47         req->in.bufinfo.align_base = req->in.buffer;
  48         req->in.bufinfo.data       = req->in.data;
  49         req->in.bufinfo.data_size  = req->in.data_size;
  50 }
  51 
  52 
  53 /* destroy a request structure and return final status */
  54 _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56         NTSTATUS status;
  57 
  58         /* this is the error code we give the application for when a
  59            _send() call fails completely */
  60         if (!req) return NT_STATUS_UNSUCCESSFUL;
  61 
  62         if (req->transport) {
  63                 /* remove it from the list of pending requests (a null op if
  64                    its not in the list) */
  65                 DLIST_REMOVE(req->transport->pending_recv, req);
  66         }
  67 
  68         if (req->state == SMBCLI_REQUEST_ERROR &&
  69             NT_STATUS_IS_OK(req->status)) {
  70                 req->status = NT_STATUS_INTERNAL_ERROR;
  71         }
  72 
  73         status = req->status;
  74 
  75         if (!req->do_not_free) {
  76                 talloc_free(req);
  77         }
  78 
  79         return status;
  80 }
  81 
  82 
  83 /*
  84   low-level function to setup a request buffer for a non-SMB packet 
  85   at the transport level
  86 */
  87 struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         struct smbcli_request *req;
  90 
  91         req = talloc(transport, struct smbcli_request);
  92         if (!req) {
  93                 return NULL;
  94         }
  95         ZERO_STRUCTP(req);
  96 
  97         /* setup the request context */
  98         req->state = SMBCLI_REQUEST_INIT;
  99         req->transport = transport;
 100         req->session = NULL;
 101         req->tree = NULL;
 102         req->out.size = size;
 103 
 104         /* over allocate by a small amount */
 105         req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
 106 
 107         req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
 108         if (!req->out.buffer) {
 109                 return NULL;
 110         }
 111 
 112         SIVAL(req->out.buffer, 0, 0);
 113 
 114         return req;
 115 }
 116 
 117 
 118 /*
 119   setup a SMB packet at transport level
 120 */
 121 struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
     /* [<][>][^][v][top][bottom][index][help] */
 122                                                       uint8_t command, uint_t wct, uint_t buflen)
 123 {
 124         struct smbcli_request *req;
 125 
 126         req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
 127 
 128         if (!req) return NULL;
 129         
 130         req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
 131         req->out.vwv = req->out.hdr + HDR_VWV;
 132         req->out.wct = wct;
 133         req->out.data = req->out.vwv + VWV(wct) + 2;
 134         req->out.data_size = buflen;
 135         req->out.ptr = req->out.data;
 136 
 137         SCVAL(req->out.hdr, HDR_WCT, wct);
 138         SSVAL(req->out.vwv, VWV(wct), buflen);
 139 
 140         memcpy(req->out.hdr, "\377SMB", 4);
 141         SCVAL(req->out.hdr,HDR_COM,command);
 142 
 143         SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
 144         SSVAL(req->out.hdr,HDR_FLG2, 0);
 145 
 146         if (command != SMBtranss && command != SMBtranss2) {
 147                 /* assign a mid */
 148                 req->mid = smbcli_transport_next_mid(transport);
 149         }
 150 
 151         /* copy the pid, uid and mid to the request */
 152         SSVAL(req->out.hdr, HDR_PID, 0);
 153         SSVAL(req->out.hdr, HDR_UID, 0);
 154         SSVAL(req->out.hdr, HDR_MID, req->mid);
 155         SSVAL(req->out.hdr, HDR_TID,0);
 156         SSVAL(req->out.hdr, HDR_PIDHIGH,0);
 157         SIVAL(req->out.hdr, HDR_RCLS, 0);
 158         memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
 159         
 160         return req;
 161 }
 162 
 163 /*
 164   setup a reply in req->out with the given word count and initial data
 165   buffer size.  the caller will then fill in the command words and
 166   data before calling smbcli_request_send() to send the reply on its
 167   way. This interface is used before a session is setup.
 168 */
 169 struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
     /* [<][>][^][v][top][bottom][index][help] */
 170                                                     uint8_t command, uint_t wct, size_t buflen)
 171 {
 172         struct smbcli_request *req;
 173 
 174         req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
 175 
 176         if (!req) return NULL;
 177 
 178         req->session = session;
 179 
 180         SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
 181         SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
 182         SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
 183         SSVAL(req->out.hdr, HDR_UID, session->vuid);
 184         
 185         return req;
 186 }
 187 
 188 /*
 189   setup a request for tree based commands
 190 */
 191 struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
     /* [<][>][^][v][top][bottom][index][help] */
 192                                             uint8_t command, 
 193                                             uint_t wct, uint_t buflen)
 194 {
 195         struct smbcli_request *req;
 196 
 197         req = smbcli_request_setup_session(tree->session, command, wct, buflen);
 198         if (req) {
 199                 req->tree = tree;
 200                 SSVAL(req->out.hdr,HDR_TID,tree->tid);
 201         }
 202         return req;
 203 }
 204 
 205 
 206 /*
 207   grow the allocation of the data buffer portion of a reply
 208   packet. Note that as this can reallocate the packet buffer this
 209   invalidates any local pointers into the packet.
 210 
 211   To cope with this req->out.ptr is supplied. This will be updated to
 212   point at the same offset into the packet as before this call
 213 */
 214 static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
     /* [<][>][^][v][top][bottom][index][help] */
 215 {
 216         int delta;
 217         uint8_t *buf2;
 218 
 219         delta = new_size - req->out.data_size;
 220         if (delta + req->out.size <= req->out.allocated) {
 221                 /* it fits in the preallocation */
 222                 return;
 223         }
 224 
 225         /* we need to realloc */
 226         req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
 227         buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
 228         if (buf2 == NULL) {
 229                 smb_panic("out of memory in req_grow_allocation");
 230         }
 231 
 232         if (buf2 == req->out.buffer) {
 233                 /* the malloc library gave us the same pointer */
 234                 return;
 235         }
 236         
 237         /* update the pointers into the packet */
 238         req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
 239         req->out.ptr  = buf2 + PTR_DIFF(req->out.ptr,  req->out.buffer);
 240         req->out.vwv  = buf2 + PTR_DIFF(req->out.vwv,  req->out.buffer);
 241         req->out.hdr  = buf2 + PTR_DIFF(req->out.hdr,  req->out.buffer);
 242 
 243         req->out.buffer = buf2;
 244 }
 245 
 246 
 247 /*
 248   grow the data buffer portion of a reply packet. Note that as this
 249   can reallocate the packet buffer this invalidates any local pointers
 250   into the packet. 
 251 
 252   To cope with this req->out.ptr is supplied. This will be updated to
 253   point at the same offset into the packet as before this call
 254 */
 255 static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257         int delta;
 258 
 259         smbcli_req_grow_allocation(req, new_size);
 260 
 261         delta = new_size - req->out.data_size;
 262 
 263         req->out.size += delta;
 264         req->out.data_size += delta;
 265 
 266         /* set the BCC to the new data size */
 267         SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
 268 }
 269 
 270 
 271 /*
 272   setup a chained reply in req->out with the given word count and
 273   initial data buffer size.
 274 */
 275 NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
 276                                       uint8_t command, 
 277                                       uint_t wct, size_t buflen)
 278 {
 279         uint_t new_size = 1 + (wct*2) + 2 + buflen;
 280 
 281         SSVAL(req->out.vwv, VWV(0), command);
 282         SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
 283 
 284         smbcli_req_grow_allocation(req, req->out.data_size + new_size);
 285 
 286         req->out.vwv = req->out.buffer + req->out.size + 1;
 287         SCVAL(req->out.vwv, -1, wct);
 288         SSVAL(req->out.vwv, VWV(wct), buflen);
 289 
 290         req->out.size += new_size;
 291         req->out.data_size += new_size;
 292 
 293         return NT_STATUS_OK;
 294 }
 295 
 296 /*
 297   aadvance to the next chained reply in a request
 298 */
 299 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 300 {
 301         uint8_t *buffer;
 302 
 303         if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
 304                 return NT_STATUS_NOT_FOUND;
 305         }
 306 
 307         buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
 308 
 309         if (buffer + 3 > req->in.buffer + req->in.size) {
 310                 return NT_STATUS_BUFFER_TOO_SMALL;
 311         }
 312 
 313         req->in.vwv = buffer + 1;
 314         req->in.wct = CVAL(buffer, 0);
 315         if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
 316                 return NT_STATUS_BUFFER_TOO_SMALL;
 317         }
 318         req->in.data = req->in.vwv + 2 + req->in.wct * 2;
 319         req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
 320 
 321         /* fix the bufinfo */
 322         smb_setup_bufinfo(req);
 323 
 324         if (buffer + 3 + req->in.wct*2 + req->in.data_size > 
 325             req->in.buffer + req->in.size) {
 326                 return NT_STATUS_BUFFER_TOO_SMALL;
 327         }
 328 
 329         return NT_STATUS_OK;
 330 }
 331 
 332 
 333 /*
 334   send a message
 335 */
 336 bool smbcli_request_send(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 337 {
 338         if (IVAL(req->out.buffer, 0) == 0) {
 339                 _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
 340         }
 341 
 342         smbcli_request_calculate_sign_mac(req);
 343 
 344         smbcli_transport_send(req);
 345 
 346         return true;
 347 }
 348 
 349 
 350 /*
 351   receive a response to a packet
 352 */
 353 bool smbcli_request_receive(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 354 {
 355         /* req can be NULL when a send has failed. This eliminates lots of NULL
 356            checks in each module */
 357         if (!req) return false;
 358 
 359         /* keep receiving packets until this one is replied to */
 360         while (req->state <= SMBCLI_REQUEST_RECV) {
 361                 if (event_loop_once(req->transport->socket->event.ctx) != 0) {
 362                         return false;
 363                 }
 364         }
 365 
 366         return req->state == SMBCLI_REQUEST_DONE;
 367 }
 368 
 369 
 370 /*
 371   handle oplock break requests from the server - return true if the request was
 372   an oplock break
 373 */
 374 bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
     /* [<][>][^][v][top][bottom][index][help] */
 375 {
 376         /* we must be very fussy about what we consider an oplock break to avoid
 377            matching readbraw replies */
 378         if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
 379             (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
 380             CVAL(hdr,HDR_COM) != SMBlockingX ||
 381             SVAL(hdr, HDR_MID) != 0xFFFF ||
 382             SVAL(vwv,VWV(6)) != 0 ||
 383             SVAL(vwv,VWV(7)) != 0) {
 384                 return false;
 385         }
 386 
 387         if (transport->oplock.handler) {
 388                 uint16_t tid = SVAL(hdr, HDR_TID);
 389                 uint16_t fnum = SVAL(vwv,VWV(2));
 390                 uint8_t level = CVAL(vwv,VWV(3)+1);
 391                 transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private_data);
 392         }
 393 
 394         return true;
 395 }
 396 
 397 /*
 398   wait for a reply to be received for a packet that just returns an error
 399   code and nothing more
 400 */
 401 _PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 402 {
 403         (void) smbcli_request_receive(req);
 404         return smbcli_request_destroy(req);
 405 }
 406 
 407 
 408 /* Return true if the last packet was in error */
 409 bool smbcli_request_is_error(struct smbcli_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 410 {
 411         return NT_STATUS_IS_ERR(req->status);
 412 }
 413 
 414 /*
 415   append a string into the data portion of the request packet
 416 
 417   return the number of bytes added to the packet
 418 */
 419 size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 420 {
 421         size_t len;
 422 
 423         /* determine string type to use */
 424         if (!(flags & (STR_ASCII|STR_UNICODE))) {
 425                 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 426         }
 427 
 428         len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;             
 429 
 430         smbcli_req_grow_allocation(req, len + req->out.data_size);
 431 
 432         len = push_string(req->out.data + req->out.data_size, str, len, flags);
 433 
 434         smbcli_req_grow_data(req, len + req->out.data_size);
 435 
 436         return len;
 437 }
 438 
 439 
 440 /*
 441   this is like smbcli_req_append_string but it also return the
 442   non-terminated string byte length, which can be less than the number
 443   of bytes consumed in the packet for 2 reasons:
 444 
 445    1) the string in the packet may be null terminated
 446    2) the string in the packet may need a 1 byte UCS2 alignment
 447 
 448  this is used in places where the non-terminated string byte length is
 449  placed in the packet as a separate field  
 450 */
 451 size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
     /* [<][>][^][v][top][bottom][index][help] */
 452 {
 453         int diff = 0;
 454         size_t ret;
 455 
 456         /* determine string type to use */
 457         if (!(flags & (STR_ASCII|STR_UNICODE))) {
 458                 flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 459         }
 460 
 461         /* see if an alignment byte will be used */
 462         if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
 463                 diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
 464         }
 465 
 466         /* do the hard work */
 467         ret = smbcli_req_append_string(req, str, flags);
 468 
 469         /* see if we need to subtract the termination */
 470         if (flags & STR_TERMINATE) {
 471                 diff += (flags & STR_UNICODE) ? 2 : 1;
 472         }
 473 
 474         if (ret >= diff) {
 475                 (*len) = ret - diff;
 476         } else {
 477                 (*len) = ret;
 478         }
 479 
 480         return ret;
 481 }
 482 
 483 
 484 /*
 485   push a string into the data portion of the request packet, growing it if necessary
 486   this gets quite tricky - please be very careful to cover all cases when modifying this
 487 
 488   if dest is NULL, then put the string at the end of the data portion of the packet
 489 
 490   if dest_len is -1 then no limit applies
 491 */
 492 size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 493 {
 494         size_t size;
 495         smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
 496         size = smbcli_req_append_string(req, str, flags);
 497         return size + 1;
 498 }
 499 
 500 
 501 /*
 502   push a blob into the data portion of the request packet, growing it if necessary
 503   this gets quite tricky - please be very careful to cover all cases when modifying this
 504 
 505   if dest is NULL, then put the blob at the end of the data portion of the packet
 506 */
 507 size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
     /* [<][>][^][v][top][bottom][index][help] */
 508 {
 509         smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
 510         memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
 511         smbcli_req_grow_data(req, req->out.data_size + blob->length);
 512         return blob->length;
 513 }
 514 
 515 /*
 516   append raw bytes into the data portion of the request packet
 517   return the number of bytes added
 518 */
 519 size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
     /* [<][>][^][v][top][bottom][index][help] */
 520 {
 521         smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
 522         memcpy(req->out.data + req->out.data_size, bytes, byte_len);
 523         smbcli_req_grow_data(req, byte_len + req->out.data_size);
 524         return byte_len;
 525 }
 526 
 527 /*
 528   append variable block (type 5 buffer) into the data portion of the request packet
 529   return the number of bytes added
 530 */
 531 size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
     /* [<][>][^][v][top][bottom][index][help] */
 532 {
 533         smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
 534         SCVAL(req->out.data + req->out.data_size, 0, 5);
 535         SSVAL(req->out.data + req->out.data_size, 1, byte_len);         /* add field length */
 536         if (byte_len > 0) {
 537                 memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
 538         }
 539         smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
 540         return byte_len + 3;
 541 }
 542 
 543 
 544 /*
 545   pull a UCS2 string from a request packet, returning a talloced unix 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 static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 558                                 char **dest, const uint8_t *src, int byte_len, uint_t flags)
 559 {
 560         int src_len, src_len2, alignment=0;
 561         bool ret;
 562         size_t ret_size;
 563 
 564         if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
 565                 src++;
 566                 alignment=1;
 567                 if (byte_len != -1) {
 568                         byte_len--;
 569                 }
 570         }
 571 
 572         src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 573         if (src_len < 0) {
 574                 *dest = NULL;
 575                 return 0;
 576         }
 577         if (byte_len != -1 && src_len > byte_len) {
 578                 src_len = byte_len;
 579         }
 580 
 581         src_len2 = utf16_len_n(src, src_len);
 582 
 583         /* ucs2 strings must be at least 2 bytes long */
 584         if (src_len2 < 2) {
 585                 *dest = NULL;
 586                 return 0;
 587         }
 588 
 589         ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
 590         if (!ret) {
 591                 *dest = NULL;
 592                 return 0;
 593         }
 594 
 595         return src_len2 + alignment;
 596 }
 597 
 598 /*
 599   pull a ascii string from a request packet, returning a talloced string
 600 
 601   the string length is limited by the 3 things:
 602    - the data size in the request (end of packet)
 603    - the passed 'byte_len' if it is not -1
 604    - the end of string (null termination)
 605 
 606   Note that 'byte_len' is the number of bytes in the packet
 607 
 608   on failure zero is returned and *dest is set to NULL, otherwise the number
 609   of bytes consumed in the packet is returned
 610 */
 611 size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 612                              char **dest, const uint8_t *src, int byte_len, uint_t flags)
 613 {
 614         int src_len, src_len2;
 615         bool ret;
 616         size_t ret_size;
 617 
 618         src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 619         if (src_len < 0) {
 620                 *dest = NULL;
 621                 return 0;
 622         }
 623         if (byte_len != -1 && src_len > byte_len) {
 624                 src_len = byte_len;
 625         }
 626         src_len2 = strnlen((const char *)src, src_len);
 627         if (src_len2 < src_len - 1) {
 628                 /* include the termination if we didn't reach the end of the packet */
 629                 src_len2++;
 630         }
 631 
 632         ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
 633 
 634         if (!ret) {
 635                 *dest = NULL;
 636                 return 0;
 637         }
 638 
 639         return ret_size;
 640 }
 641 
 642 /**
 643   pull a string from a request packet, returning a talloced string
 644 
 645   the string length is limited by the 3 things:
 646    - the data size in the request (end of packet)
 647    - the passed 'byte_len' if it is not -1
 648    - the end of string (null termination)
 649 
 650   Note that 'byte_len' is the number of bytes in the packet
 651 
 652   on failure zero is returned and *dest is set to NULL, otherwise the number
 653   of bytes consumed in the packet is returned
 654 */
 655 size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 656                            char **dest, const uint8_t *src, int byte_len, uint_t flags)
 657 {
 658         if (!(flags & STR_ASCII) && 
 659             (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
 660                 return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
 661         }
 662 
 663         return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
 664 }
 665 
 666 
 667 /**
 668   pull a DATA_BLOB from a reply packet, returning a talloced blob
 669   make sure we don't go past end of packet
 670 
 671   if byte_len is -1 then limit the blob only by packet size
 672 */
 673 DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
     /* [<][>][^][v][top][bottom][index][help] */
 674 {
 675         int src_len;
 676 
 677         src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 678 
 679         if (src_len < 0) {
 680                 return data_blob(NULL, 0);
 681         }
 682 
 683         if (byte_len != -1 && src_len > byte_len) {
 684                 src_len = byte_len;
 685         }
 686 
 687         return data_blob_talloc(mem_ctx, src, src_len);
 688 }
 689 
 690 /* check that a lump of data in a request is within the bounds of the data section of
 691    the packet */
 692 static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
     /* [<][>][^][v][top][bottom][index][help] */
 693 {
 694         /* be careful with wraparound! */
 695         if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
 696             (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
 697             count > bufinfo->data_size ||
 698             (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
 699                 return true;
 700         }
 701         return false;
 702 }
 703 
 704 /*
 705   pull a lump of data from a request packet
 706 
 707   return false if any part is outside the data portion of the packet
 708 */
 709 bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
     /* [<][>][^][v][top][bottom][index][help] */
 710 {
 711         if (len == 0) return true;
 712 
 713         if (smbcli_req_data_oob(bufinfo, src, len)) {
 714                 return false;
 715         }
 716 
 717         memcpy(dest, src, len);
 718         return true;
 719 }
 720 
 721 
 722 /*
 723   put a NTTIME into a packet
 724 */
 725 void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
     /* [<][>][^][v][top][bottom][index][help] */
 726 {
 727         SBVAL(base, offset, t);
 728 }
 729 
 730 /*
 731   pull a NTTIME from a packet
 732 */
 733 NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
     /* [<][>][^][v][top][bottom][index][help] */
 734 {
 735         NTTIME ret = BVAL(base, offset);
 736         return ret;
 737 }
 738 
 739 /**
 740   pull a UCS2 string from a blob, returning a talloced unix string
 741 
 742   the string length is limited by the 3 things:
 743    - the data size in the blob
 744    - the passed 'byte_len' if it is not -1
 745    - the end of string (null termination)
 746 
 747   Note that 'byte_len' is the number of bytes in the packet
 748 
 749   on failure zero is returned and *dest is set to NULL, otherwise the number
 750   of bytes consumed in the blob is returned
 751 */
 752 size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 753                              const DATA_BLOB *blob, const char **dest, 
 754                              const uint8_t *src, int byte_len, uint_t flags)
 755 {
 756         int src_len, src_len2, alignment=0;
 757         size_t ret_size;
 758         bool ret;
 759         char *dest2;
 760 
 761         if (src < blob->data ||
 762             src >= (blob->data + blob->length)) {
 763                 *dest = NULL;
 764                 return 0;
 765         }
 766 
 767         src_len = blob->length - PTR_DIFF(src, blob->data);
 768 
 769         if (byte_len != -1 && src_len > byte_len) {
 770                 src_len = byte_len;
 771         }
 772 
 773         if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
 774                 src++;
 775                 alignment=1;
 776                 src_len--;
 777         }
 778 
 779         if (src_len < 2) {
 780                 *dest = NULL;
 781                 return 0;
 782         }
 783 
 784         src_len2 = utf16_len_n(src, src_len);
 785 
 786         ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
 787         if (!ret) {
 788                 *dest = NULL;
 789                 return 0;
 790         }
 791         *dest = dest2;
 792 
 793         return src_len2 + alignment;
 794 }
 795 
 796 /**
 797   pull a ascii string from a blob, returning a talloced string
 798 
 799   the string length is limited by the 3 things:
 800    - the data size in the blob
 801    - the passed 'byte_len' if it is not -1
 802    - the end of string (null termination)
 803 
 804   Note that 'byte_len' is the number of bytes in the blob
 805 
 806   on failure zero is returned and *dest is set to NULL, otherwise the number
 807   of bytes consumed in the blob is returned
 808 */
 809 static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 810                                      const DATA_BLOB *blob, const char **dest, 
 811                                      const uint8_t *src, int byte_len, uint_t flags)
 812 {
 813         int src_len, src_len2;
 814         size_t ret_size;
 815         bool ret;
 816         char *dest2;
 817 
 818         src_len = blob->length - PTR_DIFF(src, blob->data);
 819         if (src_len < 0) {
 820                 *dest = NULL;
 821                 return 0;
 822         }
 823         if (byte_len != -1 && src_len > byte_len) {
 824                 src_len = byte_len;
 825         }
 826         src_len2 = strnlen((const char *)src, src_len);
 827 
 828         if (src_len2 < src_len - 1) {
 829                 /* include the termination if we didn't reach the end of the packet */
 830                 src_len2++;
 831         }
 832 
 833         ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
 834 
 835         if (!ret) {
 836                 *dest = NULL;
 837                 return 0;
 838         }
 839         *dest = dest2;
 840 
 841         return ret_size;
 842 }
 843 
 844 /**
 845   pull a string from a blob, returning a talloced struct smb_wire_string
 846 
 847   the string length is limited by the 3 things:
 848    - the data size in the blob
 849    - length field on the wire
 850    - the end of string (null termination)
 851 
 852    if STR_LEN8BIT is set in the flags then assume the length field is
 853    8 bits, instead of 32
 854 
 855   on failure zero is returned and dest->s is set to NULL, otherwise the number
 856   of bytes consumed in the blob is returned
 857 */
 858 size_t smbcli_blob_pull_string(struct smbcli_session *session,
     /* [<][>][^][v][top][bottom][index][help] */
 859                                TALLOC_CTX *mem_ctx,
 860                                const DATA_BLOB *blob, 
 861                                struct smb_wire_string *dest, 
 862                                uint16_t len_offset, uint16_t str_offset, 
 863                                uint_t flags)
 864 {
 865         int extra;
 866         dest->s = NULL;
 867 
 868         if (!(flags & STR_ASCII)) {
 869                 /* this is here to cope with SMB2 calls using the SMB
 870                    parsers. SMB2 will pass smbcli_session==NULL, which forces
 871                    unicode on (as used by SMB2) */
 872                 if (session == NULL) {
 873                         flags |= STR_UNICODE;
 874                 } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
 875                         flags |= STR_UNICODE;
 876                 }
 877         }
 878 
 879         if (flags & STR_LEN8BIT) {
 880                 if (len_offset > blob->length-1) {
 881                         return 0;
 882                 }
 883                 dest->private_length = CVAL(blob->data, len_offset);
 884         } else {
 885                 if (len_offset > blob->length-4) {
 886                         return 0;
 887                 }
 888                 dest->private_length = IVAL(blob->data, len_offset);
 889         }
 890         extra = 0;
 891         dest->s = NULL;
 892         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
 893                 int align = 0;
 894                 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
 895                         align = 1;
 896                 }
 897                 if (flags & STR_LEN_NOTERM) {
 898                         extra = 2;
 899                 }
 900                 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s, 
 901                                                           blob->data+str_offset+align, 
 902                                                           dest->private_length, flags);
 903         }
 904 
 905         if (flags & STR_LEN_NOTERM) {
 906                 extra = 1;
 907         }
 908 
 909         return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s, 
 910                                            blob->data+str_offset, dest->private_length, flags);
 911 }
 912 
 913 /**
 914   pull a string from a blob, returning a talloced char *
 915 
 916   Currently only used by the UNIX search info level.
 917 
 918   the string length is limited by 2 things:
 919    - the data size in the blob
 920    - the end of string (null termination)
 921 
 922   on failure zero is returned and dest->s is set to NULL, otherwise the number
 923   of bytes consumed in the blob is returned
 924 */
 925 size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
     /* [<][>][^][v][top][bottom][index][help] */
 926                             TALLOC_CTX *mem_ctx,
 927                             DATA_BLOB *blob, 
 928                             const char **dest, 
 929                             uint16_t str_offset, 
 930                             uint_t flags)
 931 {
 932         int extra = 0;
 933         *dest = NULL;
 934         
 935         if (!(flags & STR_ASCII) && 
 936             ((flags & STR_UNICODE) || 
 937              (session->transport->negotiate.capabilities & CAP_UNICODE))) {
 938                 int align = 0;
 939                 if ((str_offset&1) && !(flags & STR_NOALIGN)) {
 940                         align = 1;
 941                 }
 942                 if (flags & STR_LEN_NOTERM) {
 943                         extra = 2;
 944                 }
 945                 return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest, 
 946                                                           blob->data+str_offset+align, 
 947                                                           -1, flags);
 948         }
 949 
 950         if (flags & STR_LEN_NOTERM) {
 951                 extra = 1;
 952         }
 953 
 954         return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
 955                                            blob->data+str_offset, -1, flags);
 956 }
 957 
 958 
 959 /*
 960   append a string into a blob
 961 */
 962 size_t smbcli_blob_append_string(struct smbcli_session *session,
     /* [<][>][^][v][top][bottom][index][help] */
 963                               TALLOC_CTX *mem_ctx, DATA_BLOB *blob, 
 964                               const char *str, uint_t flags)
 965 {
 966         size_t max_len;
 967         int len;
 968 
 969         if (!str) return 0;
 970 
 971         /* determine string type to use */
 972         if (!(flags & (STR_ASCII|STR_UNICODE))) {
 973                 flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 974         }
 975 
 976         max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;         
 977 
 978         blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
 979         if (!blob->data) {
 980                 return 0;
 981         }
 982 
 983         len = push_string(blob->data + blob->length, str, max_len, flags);
 984 
 985         blob->length += len;
 986 
 987         return len;
 988 }
 989 
 990 /*
 991   pull a GUID structure from the wire. The buffer must be at least 16
 992   bytes long
 993  */
 994 enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset, 
     /* [<][>][^][v][top][bottom][index][help] */
 995                                    struct GUID *guid)
 996 {
 997         DATA_BLOB blob;
 998         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
 999         enum ndr_err_code ndr_err;
1000 
1001         ZERO_STRUCTP(guid);
1002 
1003         blob.data       = offset + (uint8_t *)base;
1004         blob.length     = 16;
1005         ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid, 
1006                                        (ndr_pull_flags_fn_t)ndr_pull_GUID);
1007         talloc_free(tmp_ctx);
1008         return ndr_err;
1009 }
1010 
1011 /*
1012   push a guid onto the wire. The buffer must hold 16 bytes
1013  */
1014 enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset, 
     /* [<][>][^][v][top][bottom][index][help] */
1015                                    const struct GUID *guid)
1016 {
1017         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1018         enum ndr_err_code ndr_err;
1019         DATA_BLOB blob;
1020         ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
1021                                        guid, (ndr_push_flags_fn_t)ndr_push_GUID);
1022         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
1023                 talloc_free(tmp_ctx);
1024                 return ndr_err;
1025         }
1026         memcpy(offset + (uint8_t *)base, blob.data, blob.length);
1027         talloc_free(tmp_ctx);
1028         return ndr_err;
1029 }

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