LCOV - code coverage report
Current view: top level - source4/smb_server/smb - request.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 270 334 80.8 %
Date: 2024-04-21 15:09:00 Functions: 28 30 93.3 %

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

Generated by: LCOV version 1.14