LCOV - code coverage report
Current view: top level - source4/smb_server/smb - search.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 99 139 71.2 %
Date: 2024-04-21 15:09:00 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMBsearch handling
       4             :    Copyright (C) Andrew Tridgell 2003
       5             :    Copyright (C) James J 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             :    This file handles the parsing of transact2 requests
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "smb_server/smb_server.h"
      26             : #include "ntvfs/ntvfs.h"
      27             : 
      28             : 
      29             : /* a structure to encapsulate the state information about 
      30             :  * an in-progress search first/next operation */
      31             : struct search_state {
      32             :         struct smbsrv_request *req;
      33             :         union smb_search_data *file;
      34             :         uint16_t last_entry_offset;
      35             : };
      36             : 
      37             : /*
      38             :   fill a single entry in a search find reply 
      39             : */
      40       12775 : static bool find_fill_info(struct smbsrv_request *req,
      41             :                            const union smb_search_data *file)
      42             : {
      43           0 :         uint8_t *p;
      44             : 
      45       12775 :         if (req->out.data_size + 43 > req_max_data(req)) {
      46           0 :                 return false;
      47             :         }
      48             :         
      49       12775 :         req_grow_data(req, req->out.data_size + 43);
      50       12775 :         p = req->out.data + req->out.data_size - 43;
      51             : 
      52       12775 :         SCVAL(p,  0, file->search.id.reserved);
      53       12775 :         memcpy(p+1, file->search.id.name, 11);
      54       12775 :         SCVAL(p, 12, file->search.id.handle);
      55       12775 :         SIVAL(p, 13, file->search.id.server_cookie);
      56       12775 :         SIVAL(p, 17, file->search.id.client_cookie);
      57       12775 :         SCVAL(p, 21, file->search.attrib);
      58       12775 :         srv_push_dos_date(req->smb_conn, p, 22, file->search.write_time);
      59       12775 :         SIVAL(p, 26, file->search.size);
      60       12775 :         memset(p+30, ' ', 12);
      61       12775 :         memcpy(p+30, file->search.name, MIN(strlen(file->search.name)+1, 12));
      62       12775 :         SCVAL(p,42,0);
      63             : 
      64       12775 :         return true;
      65             : }
      66             : 
      67             : /* callback function for search first/next */
      68       12775 : static bool find_callback(void *private_data, const union smb_search_data *file)
      69             : {
      70       12775 :         struct search_state *state = (struct search_state *)private_data;
      71             : 
      72       12775 :         return find_fill_info(state->req, file);
      73             : }
      74             : 
      75             : /****************************************************************************
      76             :  Reply to a search first (async reply)
      77             : ****************************************************************************/
      78          36 : static void reply_search_first_send(struct ntvfs_request *ntvfs)
      79             : {
      80           0 :         struct smbsrv_request *req;
      81           0 :         union smb_search_first *sf;
      82             : 
      83          36 :         SMBSRV_CHECK_ASYNC_STATUS(sf, union smb_search_first);
      84             : 
      85          33 :         SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count);
      86             : 
      87          33 :         smbsrv_send_reply(req);
      88             : }
      89             : 
      90             : /****************************************************************************
      91             :  Reply to a search next (async reply)
      92             : ****************************************************************************/
      93          77 : static void reply_search_next_send(struct ntvfs_request *ntvfs)
      94             : {
      95           0 :         struct smbsrv_request *req;
      96           0 :         union smb_search_next *sn;
      97             :         
      98          77 :         SMBSRV_CHECK_ASYNC_STATUS(sn, union smb_search_next);
      99             : 
     100          77 :         SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count);
     101             : 
     102          77 :         smbsrv_send_reply(req);
     103             : }
     104             : 
     105             : /****************************************************************************
     106             :  Reply to a search.
     107             : ****************************************************************************/
     108         113 : void smbsrv_reply_search(struct smbsrv_request *req)
     109             : {
     110           0 :         union smb_search_first *sf;
     111           0 :         uint16_t resume_key_length;
     112           0 :         struct search_state *state;
     113           0 :         uint8_t *p;
     114         113 :         enum smb_search_level level = RAW_SEARCH_SEARCH;
     115         113 :         uint8_t op = CVAL(req->in.hdr,HDR_COM);
     116             : 
     117         113 :         if (op == SMBffirst) {
     118           2 :                 level = RAW_SEARCH_FFIRST;
     119         111 :         } else if (op == SMBfunique) {
     120           2 :                 level = RAW_SEARCH_FUNIQUE;
     121             :         }
     122             : 
     123             :         /* parse request */
     124         113 :         if (req->in.wct != 2) {
     125           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     126           0 :                 return;
     127             :         }
     128             : 
     129         113 :         SMBSRV_TALLOC_IO_PTR(sf, union smb_search_first);
     130             : 
     131         113 :         p = req->in.data;
     132         113 :         p += req_pull_ascii4(&req->in.bufinfo, &sf->search_first.in.pattern, 
     133             :                              p, STR_TERMINATE);
     134         113 :         if (!sf->search_first.in.pattern) {
     135           0 :                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     136           0 :                 return;
     137             :         }
     138             : 
     139         113 :         if (req_data_oob(&req->in.bufinfo, p, 3)) {
     140           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     141           0 :                 return;
     142             :         }
     143         113 :         if (*p != 5) {
     144           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     145           0 :                 return;
     146             :         }
     147         113 :         resume_key_length = SVAL(p, 1);
     148         113 :         p += 3;
     149             :         
     150             :         /* setup state for callback */
     151         113 :         state = talloc(req, struct search_state);
     152         113 :         if (!state) {
     153           0 :                 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
     154           0 :                 return;
     155             :         }
     156             : 
     157         113 :         state->req = req;
     158         113 :         state->file = NULL;
     159         113 :         state->last_entry_offset = 0;
     160             : 
     161             :         /* construct reply */
     162         113 :         smbsrv_setup_reply(req, 1, 0);
     163         113 :         SSVAL(req->out.vwv, VWV(0), 0);
     164         113 :         req_append_var_block(req, NULL, 0);
     165             : 
     166         113 :         if (resume_key_length != 0) {
     167           0 :                 union smb_search_next *sn;
     168             : 
     169         154 :                 if (resume_key_length != 21 || 
     170         154 :                     req_data_oob(&req->in.bufinfo, p, 21) ||
     171             :                     level == RAW_SEARCH_FUNIQUE) {
     172           0 :                         smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     173           0 :                         return;
     174             :                 }
     175             : 
     176             :                 /* do a search next operation */
     177          77 :                 SMBSRV_TALLOC_IO_PTR(sn, union smb_search_next);
     178          77 :                 SMBSRV_SETUP_NTVFS_REQUEST(reply_search_next_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     179             : 
     180          77 :                 sn->search_next.in.id.reserved      = CVAL(p, 0);
     181          77 :                 memcpy(sn->search_next.in.id.name,    p+1, 11);
     182          77 :                 sn->search_next.in.id.handle        = CVAL(p, 12);
     183          77 :                 sn->search_next.in.id.server_cookie = IVAL(p, 13);
     184          77 :                 sn->search_next.in.id.client_cookie = IVAL(p, 17);
     185             : 
     186          77 :                 sn->search_next.level = level;
     187          77 :                 sn->search_next.data_level = RAW_SEARCH_DATA_SEARCH;
     188          77 :                 sn->search_next.in.max_count     = SVAL(req->in.vwv, VWV(0));
     189          77 :                 sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1));
     190             : 
     191             :                 /* call backend */
     192          77 :                 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_next(req->ntvfs, sn, state, find_callback));
     193             :         } else {
     194          36 :                 SMBSRV_SETUP_NTVFS_REQUEST(reply_search_first_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     195             : 
     196             :                 /* do a search first operation */
     197          36 :                 sf->search_first.level = level;
     198          36 :                 sf->search_first.data_level = RAW_SEARCH_DATA_SEARCH;
     199          36 :                 sf->search_first.in.search_attrib = SVAL(req->in.vwv, VWV(1));
     200          36 :                 sf->search_first.in.max_count     = SVAL(req->in.vwv, VWV(0));
     201             : 
     202          36 :                 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_first(req->ntvfs, sf, state, find_callback));
     203             :         }
     204             : }
     205             : 
     206             : 
     207             : /****************************************************************************
     208             :  Reply to a fclose (async reply)
     209             : ****************************************************************************/
     210           1 : static void reply_fclose_send(struct ntvfs_request *ntvfs)
     211             : {
     212           0 :         struct smbsrv_request *req;
     213             : 
     214           1 :         SMBSRV_CHECK_ASYNC_STATUS_SIMPLE;
     215             : 
     216             :         /* construct reply */
     217           1 :         smbsrv_setup_reply(req, 1, 0);
     218             : 
     219           1 :         SSVAL(req->out.vwv, VWV(0), 0);
     220             : 
     221           1 :         smbsrv_send_reply(req);
     222             : }
     223             : 
     224             : 
     225             : /****************************************************************************
     226             :  Reply to fclose (stop directory search).
     227             : ****************************************************************************/
     228           1 : void smbsrv_reply_fclose(struct smbsrv_request *req)
     229             : {
     230           0 :         union smb_search_close *sc;
     231           0 :         uint16_t resume_key_length;
     232           0 :         uint8_t *p;
     233           0 :         const char *pattern;
     234             : 
     235             :         /* parse request */
     236           1 :         if (req->in.wct != 2) {
     237           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     238           0 :                 return;
     239             :         }
     240             : 
     241           1 :         SMBSRV_TALLOC_IO_PTR(sc, union smb_search_close);
     242           1 :         SMBSRV_SETUP_NTVFS_REQUEST(reply_fclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     243             : 
     244           1 :         p = req->in.data;
     245           1 :         p += req_pull_ascii4(&req->in.bufinfo, &pattern, p, STR_TERMINATE);
     246           1 :         if (pattern && *pattern) {
     247           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     248           0 :                 return;
     249             :         }
     250             :         
     251           1 :         if (req_data_oob(&req->in.bufinfo, p, 3)) {
     252           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     253           0 :                 return;
     254             :         }
     255           1 :         if (*p != 5) {
     256           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     257           0 :                 return;
     258             :         }
     259           1 :         resume_key_length = SVAL(p, 1);
     260           1 :         p += 3;
     261             : 
     262           1 :         if (resume_key_length != 21) {
     263           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     264           0 :                 return;
     265             :         }
     266             : 
     267           1 :         if (req_data_oob(&req->in.bufinfo, p, 21)) {
     268           0 :                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
     269           0 :                 return;
     270             :         }
     271             : 
     272           1 :         sc->fclose.level               = RAW_FINDCLOSE_FCLOSE;
     273           1 :         sc->fclose.in.max_count        = SVAL(req->in.vwv, VWV(0));
     274           1 :         sc->fclose.in.search_attrib    = SVAL(req->in.vwv, VWV(1));
     275           1 :         sc->fclose.in.id.reserved      = CVAL(p, 0);
     276           1 :         memcpy(sc->fclose.in.id.name,    p+1, 11);
     277           1 :         sc->fclose.in.id.handle        = CVAL(p, 12);
     278           1 :         sc->fclose.in.id.server_cookie = IVAL(p, 13);
     279           1 :         sc->fclose.in.id.client_cookie = IVAL(p, 17);
     280             : 
     281           1 :         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req->ntvfs, sc));
     282             : 
     283             : }

Generated by: LCOV version 1.14