LCOV - code coverage report
Current view: top level - source4/libcli/raw - rawsearch.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 333 436 76.4 %
Date: 2024-06-13 04:01:37 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    client directory search routines
       4             :    Copyright (C) James Myers 2003 <myersjj@samba.org>
       5             :    Copyright (C) James Peach 2007
       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             : #include "includes.h"
      22             : #include "libcli/raw/libcliraw.h"
      23             : #include "libcli/raw/raw_proto.h"
      24             : 
      25             : /****************************************************************************
      26             :  Old style search backend - process output.
      27             : ****************************************************************************/
      28         110 : static void smb_raw_search_backend(struct smbcli_request *req,
      29             :                                    TALLOC_CTX *mem_ctx,
      30             :                                    uint16_t count, 
      31             :                                    void *private_data,
      32             :                                    smbcli_search_callback callback)
      33             : 
      34             : {
      35             :         union smb_search_data search_data;
      36             :         int i;
      37             :         uint8_t *p;
      38             : 
      39         110 :         if (req->in.data_size < 3 + count*43) {
      40           0 :                 req->status = NT_STATUS_INVALID_PARAMETER;
      41           0 :                 return;
      42             :         }
      43             :         
      44         110 :         p = req->in.data + 3;
      45             : 
      46       12885 :         for (i=0; i < count; i++) {
      47             :                 char *name;
      48             : 
      49       12775 :                 search_data.search.id.reserved      = CVAL(p, 0);
      50       12775 :                 memcpy(search_data.search.id.name,    p+1, 11);
      51       12775 :                 search_data.search.id.handle        = CVAL(p, 12);
      52       12775 :                 search_data.search.id.server_cookie = IVAL(p, 13);
      53       12775 :                 search_data.search.id.client_cookie = IVAL(p, 17);
      54       12775 :                 search_data.search.attrib           = CVAL(p, 21);
      55       12775 :                 search_data.search.write_time       = raw_pull_dos_date(req->transport,
      56       12775 :                                                                         p + 22);
      57       12775 :                 search_data.search.size             = IVAL(p, 26);
      58       12775 :                 smbcli_req_pull_ascii(&req->in.bufinfo, mem_ctx, &name, p+30, 13, STR_ASCII);
      59       12775 :                 search_data.search.name = name;
      60       12775 :                 if (!callback(private_data, &search_data)) {
      61           0 :                         break;
      62             :                 }
      63       12775 :                 p += 43;
      64             :         }
      65             : }
      66             : 
      67             : /****************************************************************************
      68             :  Old style search first.
      69             : ****************************************************************************/
      70          36 : static NTSTATUS smb_raw_search_first_old(struct smbcli_tree *tree,
      71             :                                          TALLOC_CTX *mem_ctx,
      72             :                                          union smb_search_first *io, void *private_data,
      73             :                                          smbcli_search_callback callback)
      74             : 
      75             : {
      76             :         struct smbcli_request *req; 
      77          36 :         uint8_t op = SMBsearch;
      78             : 
      79          36 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
      80           2 :                 op = SMBffirst;
      81          34 :         } else if (io->generic.level == RAW_SEARCH_FUNIQUE) {
      82           2 :                 op = SMBfunique;
      83             :         }
      84             : 
      85          36 :         req = smbcli_request_setup(tree, op, 2, 0);
      86          36 :         if (!req) {
      87           0 :                 return NT_STATUS_NO_MEMORY;
      88             :         }
      89             :         
      90          36 :         SSVAL(req->out.vwv, VWV(0), io->search_first.in.max_count);
      91          36 :         SSVAL(req->out.vwv, VWV(1), io->search_first.in.search_attrib);
      92          36 :         smbcli_req_append_ascii4(req, io->search_first.in.pattern, STR_TERMINATE);
      93          36 :         smbcli_req_append_var_block(req, NULL, 0);
      94             : 
      95          72 :         if (!smbcli_request_send(req) || 
      96          36 :             !smbcli_request_receive(req)) {
      97           0 :                 return smbcli_request_destroy(req);
      98             :         }
      99             : 
     100          36 :         if (NT_STATUS_IS_OK(req->status)) {
     101          33 :                 io->search_first.out.count = SVAL(req->in.vwv, VWV(0));   
     102          33 :                 smb_raw_search_backend(req, mem_ctx, io->search_first.out.count, private_data, callback);
     103             :         }
     104             : 
     105          36 :         return smbcli_request_destroy(req);
     106             : }
     107             : 
     108             : /****************************************************************************
     109             :  Old style search next.
     110             : ****************************************************************************/
     111          77 : static NTSTATUS smb_raw_search_next_old(struct smbcli_tree *tree,
     112             :                                         TALLOC_CTX *mem_ctx,
     113             :                                         union smb_search_next *io, void *private_data,
     114             :                                         smbcli_search_callback callback)
     115             : 
     116             : {
     117             :         struct smbcli_request *req; 
     118             :         uint8_t var_block[21];
     119          77 :         uint8_t op = SMBsearch;
     120             : 
     121          77 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
     122           0 :                 op = SMBffirst;
     123             :         }
     124             :         
     125          77 :         req = smbcli_request_setup(tree, op, 2, 0);
     126          77 :         if (!req) {
     127           0 :                 return NT_STATUS_NO_MEMORY;
     128             :         }
     129             :         
     130          77 :         SSVAL(req->out.vwv, VWV(0), io->search_next.in.max_count);
     131          77 :         SSVAL(req->out.vwv, VWV(1), io->search_next.in.search_attrib);
     132          77 :         smbcli_req_append_ascii4(req, "", STR_TERMINATE);
     133             : 
     134          77 :         SCVAL(var_block,  0, io->search_next.in.id.reserved);
     135          77 :         memcpy(&var_block[1], io->search_next.in.id.name, 11);
     136          77 :         SCVAL(var_block, 12, io->search_next.in.id.handle);
     137          77 :         SIVAL(var_block, 13, io->search_next.in.id.server_cookie);
     138          77 :         SIVAL(var_block, 17, io->search_next.in.id.client_cookie);
     139             : 
     140          77 :         smbcli_req_append_var_block(req, var_block, 21);
     141             : 
     142         154 :         if (!smbcli_request_send(req) ||
     143          77 :             !smbcli_request_receive(req)) {
     144           0 :                 return smbcli_request_destroy(req);
     145             :         }
     146             : 
     147          77 :         if (NT_STATUS_IS_OK(req->status)) {
     148          77 :                 io->search_next.out.count = SVAL(req->in.vwv, VWV(0));
     149          77 :                 smb_raw_search_backend(req, mem_ctx, io->search_next.out.count, private_data, callback);
     150             :         }
     151             :         
     152          77 :         return smbcli_request_destroy(req);
     153             : }
     154             : 
     155             : 
     156             : /****************************************************************************
     157             :  Old style search next.
     158             : ****************************************************************************/
     159           1 : static NTSTATUS smb_raw_search_close_old(struct smbcli_tree *tree,
     160             :                                          union smb_search_close *io)
     161             : {
     162             :         struct smbcli_request *req; 
     163             :         uint8_t var_block[21];
     164             : 
     165           1 :         req = smbcli_request_setup(tree, SMBfclose, 2, 0);
     166           1 :         if (!req) {
     167           0 :                 return NT_STATUS_NO_MEMORY;
     168             :         }
     169             :         
     170           1 :         SSVAL(req->out.vwv, VWV(0), io->fclose.in.max_count);
     171           1 :         SSVAL(req->out.vwv, VWV(1), io->fclose.in.search_attrib);
     172           1 :         smbcli_req_append_ascii4(req, "", STR_TERMINATE);
     173             : 
     174           1 :         SCVAL(var_block,  0, io->fclose.in.id.reserved);
     175           1 :         memcpy(&var_block[1], io->fclose.in.id.name, 11);
     176           1 :         SCVAL(var_block, 12, io->fclose.in.id.handle);
     177           1 :         SIVAL(var_block, 13, io->fclose.in.id.server_cookie);
     178           1 :         SIVAL(var_block, 17, io->fclose.in.id.client_cookie);
     179             : 
     180           1 :         smbcli_req_append_var_block(req, var_block, 21);
     181             : 
     182           2 :         if (!smbcli_request_send(req) ||
     183           1 :             !smbcli_request_receive(req)) {
     184           0 :                 return smbcli_request_destroy(req);
     185             :         }
     186             : 
     187           1 :         return smbcli_request_destroy(req);
     188             : }
     189             : 
     190             : 
     191             : 
     192             : /****************************************************************************
     193             :  Very raw search first - returns param/data blobs.
     194             : ****************************************************************************/
     195        6219 : static NTSTATUS smb_raw_search_first_blob(struct smbcli_tree *tree,
     196             :                                           TALLOC_CTX *mem_ctx,  /* used to allocate output blobs */
     197             :                                           union smb_search_first *io,
     198             :                                           DATA_BLOB *out_param_blob,
     199             :                                           DATA_BLOB *out_data_blob)
     200             : {
     201             :         struct smb_trans2 tp;
     202        6219 :         uint16_t setup = TRANSACT2_FINDFIRST;
     203             :         NTSTATUS status;
     204             :         
     205        6219 :         tp.in.max_setup = 0;
     206        6219 :         tp.in.flags = 0; 
     207        6219 :         tp.in.timeout = 0;
     208        6219 :         tp.in.setup_count = 1;
     209        6219 :         tp.in.data = data_blob(NULL, 0);
     210        6219 :         tp.in.max_param = 10;
     211        6219 :         tp.in.max_data = 0xFFFF;
     212        6219 :         tp.in.setup = &setup;
     213             : 
     214        6219 :         if (io->t2ffirst.level != RAW_SEARCH_TRANS2) {
     215           0 :                 return NT_STATUS_INVALID_LEVEL;
     216             :         }
     217             : 
     218        6219 :         if (io->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) {
     219           0 :                 return NT_STATUS_INVALID_LEVEL;
     220             :         }
     221             : 
     222        6219 :         if (io->t2ffirst.data_level == RAW_SEARCH_DATA_EA_LIST) {
     223           1 :                 if (!ea_push_name_list(mem_ctx, 
     224             :                                        &tp.in.data,
     225             :                                        io->t2ffirst.in.num_names,
     226             :                                        io->t2ffirst.in.ea_names)) {
     227           0 :                         return NT_STATUS_NO_MEMORY;
     228             :                 }               
     229             :         }
     230             : 
     231        6219 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     232        6219 :         if (!tp.in.params.data) {
     233           0 :                 return NT_STATUS_NO_MEMORY;
     234             :         }
     235             : 
     236        6219 :         SSVAL(tp.in.params.data, 0, io->t2ffirst.in.search_attrib);
     237        6219 :         SSVAL(tp.in.params.data, 2, io->t2ffirst.in.max_count);      
     238        6219 :         SSVAL(tp.in.params.data, 4, io->t2ffirst.in.flags);
     239        6219 :         SSVAL(tp.in.params.data, 6, io->t2ffirst.data_level);
     240        6219 :         SIVAL(tp.in.params.data, 8, io->t2ffirst.in.storage_type);
     241             : 
     242        6219 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     243             :                                   io->t2ffirst.in.pattern, STR_TERMINATE);
     244             : 
     245        6219 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     246        6219 :         if (!NT_STATUS_IS_OK(status)) {
     247        2277 :                 return status;
     248             :         }
     249             : 
     250        3942 :         out_param_blob->length = tp.out.params.length;
     251        3942 :         out_param_blob->data = tp.out.params.data;
     252        3942 :         out_data_blob->length = tp.out.data.length;
     253        3942 :         out_data_blob->data = tp.out.data.data;
     254             : 
     255        3942 :         return NT_STATUS_OK;
     256             : }
     257             : 
     258             : 
     259             : /****************************************************************************
     260             :  Very raw search first - returns param/data blobs.
     261             :  Used in CIFS-on-CIFS NTVFS.
     262             : ****************************************************************************/
     263         341 : static NTSTATUS smb_raw_search_next_blob(struct smbcli_tree *tree,
     264             :                                          TALLOC_CTX *mem_ctx,
     265             :                                          union smb_search_next *io,
     266             :                                          DATA_BLOB *out_param_blob,
     267             :                                          DATA_BLOB *out_data_blob)
     268             : {
     269             :         struct smb_trans2 tp;
     270         341 :         uint16_t setup = TRANSACT2_FINDNEXT;
     271             :         NTSTATUS status;
     272             :         
     273         341 :         tp.in.max_setup = 0;
     274         341 :         tp.in.flags = 0; 
     275         341 :         tp.in.timeout = 0;
     276         341 :         tp.in.setup_count = 1;
     277         341 :         tp.in.data = data_blob(NULL, 0);
     278         341 :         tp.in.max_param = 10;
     279         341 :         tp.in.max_data = 0xFFFF;
     280         341 :         tp.in.setup = &setup;
     281             : 
     282         341 :         if (io->t2fnext.level != RAW_SEARCH_TRANS2) {
     283           0 :                 return NT_STATUS_INVALID_LEVEL;
     284             :         }
     285             : 
     286         341 :         if (io->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {
     287           0 :                 return NT_STATUS_INVALID_LEVEL;
     288             :         }
     289             : 
     290         341 :         if (io->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) {
     291           1 :                 if (!ea_push_name_list(mem_ctx, 
     292             :                                        &tp.in.data,
     293             :                                        io->t2fnext.in.num_names,
     294             :                                        io->t2fnext.in.ea_names)) {
     295           0 :                         return NT_STATUS_NO_MEMORY;
     296             :                 }               
     297             :         }
     298             :         
     299         341 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     300         341 :         if (!tp.in.params.data) {
     301           0 :                 return NT_STATUS_NO_MEMORY;
     302             :         }
     303             :         
     304         341 :         SSVAL(tp.in.params.data, 0, io->t2fnext.in.handle);
     305         341 :         SSVAL(tp.in.params.data, 2, io->t2fnext.in.max_count);
     306         341 :         SSVAL(tp.in.params.data, 4, io->t2fnext.data_level);
     307         341 :         SIVAL(tp.in.params.data, 6, io->t2fnext.in.resume_key);
     308         341 :         SSVAL(tp.in.params.data, 10, io->t2fnext.in.flags);
     309             : 
     310         341 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     311             :                                io->t2fnext.in.last_name,
     312             :                                STR_TERMINATE);
     313             : 
     314         341 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     315         341 :         if (!NT_STATUS_IS_OK(status)) {
     316           0 :                 return status;
     317             :         }
     318             : 
     319         341 :         out_param_blob->length = tp.out.params.length;
     320         341 :         out_param_blob->data = tp.out.params.data;
     321         341 :         out_data_blob->length = tp.out.data.length;
     322         341 :         out_data_blob->data = tp.out.data.data;
     323             : 
     324         341 :         return NT_STATUS_OK;
     325             : }
     326             : 
     327             : 
     328             : /*
     329             :   parse the wire search formats that are in common between SMB and
     330             :   SMB2
     331             : */
     332       93368 : NTSTATUS smb_raw_search_common(TALLOC_CTX *mem_ctx, 
     333             :                                enum smb_search_data_level level,
     334             :                                const DATA_BLOB *blob,
     335             :                                union smb_search_data *data,
     336             :                                unsigned int *next_ofs,
     337             :                                unsigned int str_flags)
     338             : {
     339             :         unsigned int len, blen;
     340             : 
     341       93368 :         if (blob->length < 4) {
     342           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     343             :         }
     344             : 
     345       93368 :         *next_ofs = IVAL(blob->data, 0);
     346       93368 :         if (*next_ofs != 0) {
     347       93214 :                 blen = *next_ofs;
     348             :         } else {
     349         154 :                 blen = blob->length;
     350             :         }
     351             : 
     352       93368 :         switch (level) {
     353        2102 :         case RAW_SEARCH_DATA_DIRECTORY_INFO:
     354        2102 :                 if (blen < 65) return NT_STATUS_INFO_LENGTH_MISMATCH;
     355        2102 :                 data->directory_info.file_index  = IVAL(blob->data,             4);
     356        2102 :                 data->directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     357        2102 :                 data->directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     358        2102 :                 data->directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     359        2102 :                 data->directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     360        2102 :                 data->directory_info.size        = BVAL(blob->data,            40);
     361        2102 :                 data->directory_info.alloc_size  = BVAL(blob->data,            48);
     362        2102 :                 data->directory_info.attrib      = IVAL(blob->data,            56);
     363        2102 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     364             :                                               &data->directory_info.name,
     365             :                                               60, 64, str_flags);
     366        2102 :                 if (*next_ofs != 0 && *next_ofs < 64+len) {
     367           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     368             :                 }
     369        2102 :                 return NT_STATUS_OK;
     370             : 
     371        2363 :         case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
     372        2363 :                 if (blen < 69) return NT_STATUS_INFO_LENGTH_MISMATCH;
     373        2363 :                 data->full_directory_info.file_index  = IVAL(blob->data,                4);
     374        2363 :                 data->full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     375        2363 :                 data->full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     376        2363 :                 data->full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     377        2363 :                 data->full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     378        2363 :                 data->full_directory_info.size        = BVAL(blob->data,               40);
     379        2363 :                 data->full_directory_info.alloc_size  = BVAL(blob->data,               48);
     380        2363 :                 data->full_directory_info.attrib      = IVAL(blob->data,               56);
     381        2363 :                 data->full_directory_info.ea_size     = IVAL(blob->data,               64);
     382        2363 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     383             :                                               &data->full_directory_info.name,
     384             :                                               60, 68, str_flags);
     385        2363 :                 if (*next_ofs != 0 && *next_ofs < 68+len) {
     386           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     387             :                 }
     388        2363 :                 return NT_STATUS_OK;
     389             : 
     390       65969 :         case RAW_SEARCH_DATA_NAME_INFO:
     391       65969 :                 if (blen < 13) return NT_STATUS_INFO_LENGTH_MISMATCH;
     392       65969 :                 data->name_info.file_index  = IVAL(blob->data, 4);
     393       65969 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     394             :                                               &data->name_info.name,
     395             :                                               8, 12, str_flags);
     396       65969 :                 if (*next_ofs != 0 && *next_ofs < 12+len) {
     397           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     398             :                 }
     399       65969 :                 return NT_STATUS_OK;
     400             : 
     401             : 
     402       18730 :         case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
     403       18730 :                 if (blen < 95) return NT_STATUS_INFO_LENGTH_MISMATCH;
     404       18730 :                 data->both_directory_info.file_index  = IVAL(blob->data,                4);
     405       18730 :                 data->both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     406       18730 :                 data->both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     407       18730 :                 data->both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     408       18730 :                 data->both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     409       18730 :                 data->both_directory_info.size        = BVAL(blob->data,               40);
     410       18730 :                 data->both_directory_info.alloc_size  = BVAL(blob->data,               48);
     411       18730 :                 data->both_directory_info.attrib      = IVAL(blob->data,               56);
     412       18730 :                 data->both_directory_info.ea_size     = IVAL(blob->data,               64);
     413       18730 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     414             :                                         &data->both_directory_info.short_name,
     415             :                                         68, 70, STR_LEN8BIT | STR_UNICODE);
     416       18730 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     417             :                                               &data->both_directory_info.name,
     418             :                                               60, 94, str_flags);
     419       18730 :                 if (*next_ofs != 0 && *next_ofs < 94+len) {
     420           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     421             :                 }
     422       18730 :                 return NT_STATUS_OK;
     423             : 
     424             : 
     425        2102 :         case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
     426        2102 :                 if (blen < 81) return NT_STATUS_INFO_LENGTH_MISMATCH;
     427        2102 :                 data->id_full_directory_info.file_index  = IVAL(blob->data,             4);
     428        2102 :                 data->id_full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     429        2102 :                 data->id_full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     430        2102 :                 data->id_full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     431        2102 :                 data->id_full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     432        2102 :                 data->id_full_directory_info.size        = BVAL(blob->data,            40);
     433        2102 :                 data->id_full_directory_info.alloc_size  = BVAL(blob->data,            48);
     434        2102 :                 data->id_full_directory_info.attrib      = IVAL(blob->data,            56);
     435        2102 :                 data->id_full_directory_info.ea_size     = IVAL(blob->data,            64);
     436        2102 :                 data->id_full_directory_info.file_id     = BVAL(blob->data,            72);
     437        2102 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     438             :                                               &data->id_full_directory_info.name,
     439             :                                               60, 80, str_flags);
     440        2102 :                 if (*next_ofs != 0 && *next_ofs < 80+len) {
     441           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     442             :                 }
     443        2102 :                 return NT_STATUS_OK;
     444             : 
     445        2102 :         case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
     446        2102 :                 if (blen < 105) return NT_STATUS_INFO_LENGTH_MISMATCH;
     447        2102 :                 data->id_both_directory_info.file_index  = IVAL(blob->data,             4);
     448        2102 :                 data->id_both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     449        2102 :                 data->id_both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     450        2102 :                 data->id_both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     451        2102 :                 data->id_both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     452        2102 :                 data->id_both_directory_info.size        = BVAL(blob->data,            40);
     453        2102 :                 data->id_both_directory_info.alloc_size  = BVAL(blob->data,            48);
     454        2102 :                 data->id_both_directory_info.attrib      = SVAL(blob->data,            56);
     455        2102 :                 data->id_both_directory_info.ea_size     = IVAL(blob->data,            64);
     456        2102 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     457             :                                      &data->id_both_directory_info.short_name,
     458             :                                      68, 70, STR_LEN8BIT | STR_UNICODE);
     459        2102 :                 memcpy(data->id_both_directory_info.short_name_buf, blob->data + 70, 24);
     460        2102 :                 data->id_both_directory_info.file_id     = BVAL(blob->data,            96);
     461        2102 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     462             :                                               &data->id_both_directory_info.name,
     463             :                                               60, 104, str_flags);
     464        2102 :                 if (*next_ofs != 0 && *next_ofs < 104+len) {
     465           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     466             :                 }
     467        2102 :                 return NT_STATUS_OK;
     468             :         
     469           0 :         default:
     470           0 :                 break;
     471             :         }
     472             : 
     473             :         /* invalid level */
     474           0 :         return NT_STATUS_INVALID_INFO_CLASS;
     475             : }
     476             : 
     477             : 
     478             : /*
     479             :   parse a trans2 search response. 
     480             :   Return the number of bytes consumed
     481             :   return 0 for success with end of list
     482             :   return -1 for a parse error
     483             : */
     484       47907 : static int parse_trans2_search(struct smbcli_tree *tree,
     485             :                                TALLOC_CTX *mem_ctx, 
     486             :                                enum smb_search_data_level level,
     487             :                                uint16_t flags,
     488             :                                DATA_BLOB *blob,
     489             :                                union smb_search_data *data)
     490             : {
     491             :         unsigned int len, ofs;
     492             :         uint32_t ea_size;
     493             :         DATA_BLOB eablob;
     494             :         NTSTATUS status;
     495             : 
     496       47907 :         switch (level) {
     497           0 :         case RAW_SEARCH_DATA_GENERIC:
     498             :         case RAW_SEARCH_DATA_SEARCH:
     499             :                 /* handled elsewhere */
     500           0 :                 return -1;
     501             : 
     502        2102 :         case RAW_SEARCH_DATA_STANDARD:
     503        2102 :                 if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
     504         700 :                         if (blob->length < 4) return -1;
     505         700 :                         data->standard.resume_key = IVAL(blob->data, 0);
     506         700 :                         blob->data += 4;
     507         700 :                         blob->length -= 4;
     508             :                 }
     509        2102 :                 if (blob->length < 24) return -1;
     510        2102 :                 data->standard.create_time = raw_pull_dos_date2(tree->session->transport,
     511        2102 :                                                                 blob->data + 0);
     512        2102 :                 data->standard.access_time = raw_pull_dos_date2(tree->session->transport,
     513        2102 :                                                                 blob->data + 4);
     514        2102 :                 data->standard.write_time  = raw_pull_dos_date2(tree->session->transport,
     515        2102 :                                                                 blob->data + 8);
     516        2102 :                 data->standard.size        = IVAL(blob->data, 12);
     517        2102 :                 data->standard.alloc_size  = IVAL(blob->data, 16);
     518        2102 :                 data->standard.attrib      = SVAL(blob->data, 20);
     519        2102 :                 len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
     520             :                                            &data->standard.name,
     521             :                                            22, 23, STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM);
     522        2102 :                 return len + 23;
     523             : 
     524       18402 :         case RAW_SEARCH_DATA_EA_SIZE:
     525       18402 :                 if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
     526       17000 :                         if (blob->length < 4) return -1;
     527       17000 :                         data->ea_size.resume_key = IVAL(blob->data, 0);
     528       17000 :                         blob->data += 4;
     529       17000 :                         blob->length -= 4;
     530             :                 }
     531       18402 :                 if (blob->length < 28) return -1;
     532       18402 :                 data->ea_size.create_time = raw_pull_dos_date2(tree->session->transport,
     533       18402 :                                                                blob->data + 0);
     534       18402 :                 data->ea_size.access_time = raw_pull_dos_date2(tree->session->transport,
     535       18402 :                                                                blob->data + 4);
     536       18402 :                 data->ea_size.write_time  = raw_pull_dos_date2(tree->session->transport,
     537       18402 :                                                                blob->data + 8);
     538       18402 :                 data->ea_size.size        = IVAL(blob->data, 12);
     539       18402 :                 data->ea_size.alloc_size  = IVAL(blob->data, 16);
     540       18402 :                 data->ea_size.attrib      = SVAL(blob->data, 20);
     541       18402 :                 data->ea_size.ea_size     = IVAL(blob->data, 22);
     542       18402 :                 len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
     543             :                                            &data->ea_size.name,
     544             :                                            26, 27, STR_LEN8BIT | STR_TERMINATE | STR_NOALIGN);
     545       18402 :                 return len + 27 + 1;
     546             : 
     547           3 :         case RAW_SEARCH_DATA_EA_LIST:
     548           3 :                 if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
     549           3 :                         if (blob->length < 4) return -1;
     550           3 :                         data->ea_list.resume_key = IVAL(blob->data, 0);
     551           3 :                         blob->data += 4;
     552           3 :                         blob->length -= 4;
     553             :                 }
     554           3 :                 if (blob->length < 28) return -1;
     555           3 :                 data->ea_list.create_time = raw_pull_dos_date2(tree->session->transport,
     556           3 :                                                                blob->data + 0);
     557           3 :                 data->ea_list.access_time = raw_pull_dos_date2(tree->session->transport,
     558           3 :                                                                blob->data + 4);
     559           3 :                 data->ea_list.write_time  = raw_pull_dos_date2(tree->session->transport,
     560           3 :                                                                blob->data + 8);
     561           3 :                 data->ea_list.size        = IVAL(blob->data, 12);
     562           3 :                 data->ea_list.alloc_size  = IVAL(blob->data, 16);
     563           3 :                 data->ea_list.attrib      = SVAL(blob->data, 20);
     564           3 :                 ea_size                   = IVAL(blob->data, 22);
     565           3 :                 if (ea_size > 0xFFFF) {
     566           0 :                         return -1;
     567             :                 }
     568           3 :                 eablob.data = blob->data + 22;
     569           3 :                 eablob.length = ea_size;
     570           3 :                 if (eablob.length > blob->length - 24) {
     571           0 :                         return -1;
     572             :                 }
     573           3 :                 status = ea_pull_list(&eablob, mem_ctx, 
     574             :                                       &data->ea_list.eas.num_eas,
     575             :                                       &data->ea_list.eas.eas);
     576           3 :                 if (!NT_STATUS_IS_OK(status)) {
     577           0 :                         return -1;
     578             :                 }
     579           6 :                 len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
     580             :                                               &data->ea_list.name,
     581           6 :                                               22+ea_size, 23+ea_size, 
     582             :                                               STR_LEN8BIT | STR_NOALIGN);
     583           3 :                 return len + ea_size + 23 + 1;
     584             : 
     585           0 :         case RAW_SEARCH_DATA_UNIX_INFO:
     586           0 :                 if (blob->length < 109) return -1;
     587           0 :                 ofs                                  = IVAL(blob->data,             0);
     588           0 :                 data->unix_info.file_index           = IVAL(blob->data,             4);
     589           0 :                 data->unix_info.size                 = BVAL(blob->data,             8);
     590           0 :                 data->unix_info.alloc_size           = BVAL(blob->data,            16);
     591           0 :                 data->unix_info.status_change_time   = smbcli_pull_nttime(blob->data, 24);
     592           0 :                 data->unix_info.access_time          = smbcli_pull_nttime(blob->data, 32);
     593           0 :                 data->unix_info.change_time          = smbcli_pull_nttime(blob->data, 40);
     594           0 :                 data->unix_info.uid                  = IVAL(blob->data,            48);
     595           0 :                 data->unix_info.gid                  = IVAL(blob->data,            56);
     596           0 :                 data->unix_info.file_type            = IVAL(blob->data,            64);
     597           0 :                 data->unix_info.dev_major            = BVAL(blob->data,            68);
     598           0 :                 data->unix_info.dev_minor            = BVAL(blob->data,            76);
     599           0 :                 data->unix_info.unique_id            = BVAL(blob->data,            84);
     600           0 :                 data->unix_info.permissions          = IVAL(blob->data,            92);
     601           0 :                 data->unix_info.nlink                = IVAL(blob->data,           100);
     602             :                 /* There is no length field for this name but we know it's null terminated. */
     603           0 :                 len = smbcli_blob_pull_unix_string(tree->session, mem_ctx, blob,
     604             :                                            &data->unix_info.name, 108, 0);
     605           0 :                 if (ofs != 0 && ofs < 108+len) {
     606           0 :                         return -1;
     607             :                 }
     608           0 :                 return ofs;
     609             : 
     610           0 :         case RAW_SEARCH_DATA_UNIX_INFO2:
     611             :                 /*   8 - size of ofs + file_index
     612             :                  * 116 - size of unix_info2
     613             :                  *   4 - size of name length
     614             :                  *   2 - "." is the shortest name
     615             :                  */
     616           0 :                 if (blob->length < (116 + 8 + 4 + 2)) {
     617           0 :                         return -1;
     618             :                 }
     619             : 
     620           0 :                 ofs                                 = IVAL(blob->data,   0);
     621           0 :                 data->unix_info2.file_index         = IVAL(blob->data,   4);
     622           0 :                 data->unix_info2.end_of_file        = BVAL(blob->data,   8);
     623           0 :                 data->unix_info2.num_bytes          = BVAL(blob->data,  16);
     624           0 :                 data->unix_info2.status_change_time = smbcli_pull_nttime(blob->data, 24);
     625           0 :                 data->unix_info2.access_time        = smbcli_pull_nttime(blob->data, 32);
     626           0 :                 data->unix_info2.change_time        = smbcli_pull_nttime(blob->data, 40);
     627           0 :                 data->unix_info2.uid                = IVAL(blob->data,  48);
     628           0 :                 data->unix_info2.gid                = IVAL(blob->data,  56);
     629           0 :                 data->unix_info2.file_type          = IVAL(blob->data,  64);
     630           0 :                 data->unix_info2.dev_major          = BVAL(blob->data,  68);
     631           0 :                 data->unix_info2.dev_minor          = BVAL(blob->data,  76);
     632           0 :                 data->unix_info2.unique_id          = BVAL(blob->data,  84);
     633           0 :                 data->unix_info2.permissions        = IVAL(blob->data,  92);
     634           0 :                 data->unix_info2.nlink              = IVAL(blob->data, 100);
     635           0 :                 data->unix_info2.create_time     = smbcli_pull_nttime(blob->data, 108);
     636           0 :                 data->unix_info2.file_flags      = IVAL(blob->data, 116);
     637           0 :                 data->unix_info2.flags_mask      = IVAL(blob->data, 120);
     638             : 
     639             :                 /* There is a 4 byte length field for this name. The length
     640             :                  * does not include the NULL terminator.
     641             :                  */
     642           0 :                 len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
     643             :                                        &data->unix_info2.name,
     644             :                                        8 + 116, /* offset to length */
     645             :                                        8 + 116 + 4, /* offset to string */
     646             :                                        0);
     647             : 
     648           0 :                 if (ofs != 0 && ofs < (8 + 116 + 4 + len)) {
     649           0 :                         return -1;
     650             :                 }
     651             : 
     652           0 :                 return ofs;
     653             : 
     654       27400 :                 case RAW_SEARCH_DATA_DIRECTORY_INFO:
     655             :                 case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
     656             :                 case RAW_SEARCH_DATA_NAME_INFO:
     657             :                 case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
     658             :                 case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
     659             :                 case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO: {
     660       27400 :                         unsigned int str_flags = STR_UNICODE;
     661       27400 :                         if (!(tree->session->transport->negotiate.capabilities & CAP_UNICODE)) {
     662           0 :                                 str_flags = STR_ASCII;
     663             :                         }
     664             :                         
     665       27400 :                 status = smb_raw_search_common(mem_ctx, level, blob, data, &ofs, str_flags);
     666       27400 :                 if (!NT_STATUS_IS_OK(status)) {
     667           0 :                         return -1;
     668             :                 }
     669       27400 :                 return ofs;
     670             :         }
     671             :         }
     672             : 
     673             :         /* invalid level */
     674           0 :         return -1;
     675             : }
     676             : 
     677             : /****************************************************************************
     678             :  Trans2 search backend - process output.
     679             : ****************************************************************************/
     680        4283 : static NTSTATUS smb_raw_t2search_backend(struct smbcli_tree *tree,
     681             :                                          TALLOC_CTX *mem_ctx,
     682             :                                          enum smb_search_data_level level,
     683             :                                          uint16_t flags,
     684             :                                          int16_t count,
     685             :                                          DATA_BLOB *blob,
     686             :                                          void *private_data,
     687             :                                          smbcli_search_callback callback)
     688             : 
     689             : {
     690             :         int i;
     691             :         DATA_BLOB blob2;
     692             : 
     693        4283 :         blob2.data = blob->data;
     694        4283 :         blob2.length = blob->length;
     695             : 
     696      104343 :         for (i=0; i < count; i++) {
     697             :                 union smb_search_data search_data;
     698             :                 unsigned int len;
     699             : 
     700       47907 :                 len = parse_trans2_search(tree, mem_ctx, level, flags, &blob2, &search_data);
     701       47907 :                 if (len == -1) {
     702           0 :                         return NT_STATUS_INVALID_PARAMETER;
     703             :                 }
     704             : 
     705             :                 /* the callback function can tell us that no more will
     706             :                    fit - in that case we stop, but it isn't an error */
     707       47907 :                 if (!callback(private_data, &search_data)) {
     708           0 :                         break;
     709             :                 }
     710             : 
     711       47907 :                 if (len == 0) break;
     712             : 
     713       47907 :                 blob2.data += len;
     714       47907 :                 blob2.length -= len;
     715             :         }
     716             : 
     717        4283 :         return NT_STATUS_OK;
     718             : }
     719             : 
     720             : 
     721             : /* Implements trans2findfirst2 and old search
     722             :  */
     723        6255 : _PUBLIC_ NTSTATUS smb_raw_search_first(struct smbcli_tree *tree,
     724             :                               TALLOC_CTX *mem_ctx,
     725             :                               union smb_search_first *io, void *private_data,
     726             :                               smbcli_search_callback callback)
     727             : {
     728        6255 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     729             :         NTSTATUS status;
     730             : 
     731        6255 :         switch (io->generic.level) {
     732          36 :         case RAW_SEARCH_SEARCH:
     733             :         case RAW_SEARCH_FFIRST:
     734             :         case RAW_SEARCH_FUNIQUE:
     735          36 :                 return smb_raw_search_first_old(tree, mem_ctx, io, private_data, callback);
     736             : 
     737        6219 :         case RAW_SEARCH_TRANS2:
     738        6219 :                 break;
     739             : 
     740           0 :         case RAW_SEARCH_SMB2:
     741           0 :                 return NT_STATUS_INVALID_LEVEL;
     742             :         }
     743             : 
     744        6219 :         status = smb_raw_search_first_blob(tree, mem_ctx,
     745             :                                            io, &p_blob, &d_blob);
     746        6219 :         if (!NT_STATUS_IS_OK(status)) {
     747        2277 :                 return status;
     748             :         }
     749             :         
     750        3942 :         if (p_blob.length < 10) {
     751           0 :                 DEBUG(1,("smb_raw_search_first: parms wrong size %d != expected_param_size\n",
     752             :                         (int)p_blob.length));
     753           0 :                 return NT_STATUS_INVALID_PARAMETER;
     754             :         }
     755             : 
     756             :         /* process output data */
     757        3942 :         io->t2ffirst.out.handle = SVAL(p_blob.data, 0);
     758        3942 :         io->t2ffirst.out.count = SVAL(p_blob.data, 2);
     759        3942 :         io->t2ffirst.out.end_of_search = SVAL(p_blob.data, 4);
     760             : 
     761        7878 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     762             :                                           io->generic.data_level, 
     763        7878 :                                           io->t2ffirst.in.flags, io->t2ffirst.out.count,
     764             :                                           &d_blob, private_data, callback);
     765             :         
     766        3942 :         return status;
     767             : }
     768             : 
     769             : /* Implements trans2findnext2 and old smbsearch
     770             :  */
     771         418 : NTSTATUS smb_raw_search_next(struct smbcli_tree *tree,
     772             :                              TALLOC_CTX *mem_ctx,
     773             :                              union smb_search_next *io, void *private_data,
     774             :                              smbcli_search_callback callback)
     775             : {
     776         418 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     777             :         NTSTATUS status;
     778             : 
     779         418 :         switch (io->generic.level) {
     780          77 :         case RAW_SEARCH_SEARCH:
     781             :         case RAW_SEARCH_FFIRST:
     782          77 :                 return smb_raw_search_next_old(tree, mem_ctx, io, private_data, callback);
     783             : 
     784           0 :         case RAW_SEARCH_FUNIQUE:
     785           0 :                 return NT_STATUS_INVALID_LEVEL;
     786             : 
     787         341 :         case RAW_SEARCH_TRANS2:
     788         341 :                 break;
     789             : 
     790           0 :         case RAW_SEARCH_SMB2:
     791           0 :                 return NT_STATUS_INVALID_LEVEL;
     792             :         }
     793             : 
     794         341 :         status = smb_raw_search_next_blob(tree, mem_ctx,
     795             :                                           io, &p_blob, &d_blob);
     796         341 :         if (!NT_STATUS_IS_OK(status)) {
     797           0 :                 return status;
     798             :         }
     799             :         
     800         341 :         if (p_blob.length != 8) {
     801           0 :                 DEBUG(1,("smb_raw_search_next: parms wrong size %d != expected_param_size\n",
     802             :                         (int)p_blob.length));
     803           0 :                 return NT_STATUS_INVALID_PARAMETER;
     804             :         }
     805             : 
     806             :         /* process output data */
     807         341 :         io->t2fnext.out.count = SVAL(p_blob.data, 0);
     808         341 :         io->t2fnext.out.end_of_search = SVAL(p_blob.data, 2);
     809             :                 
     810         682 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     811             :                                           io->generic.data_level, 
     812         682 :                                           io->t2fnext.in.flags, io->t2fnext.out.count,
     813             :                                           &d_blob, private_data, callback);
     814             :         
     815         341 :         return status;
     816             : }
     817             : 
     818             : /* 
     819             :    Implements trans2findclose2
     820             :  */
     821           1 : NTSTATUS smb_raw_search_close(struct smbcli_tree *tree,
     822             :                               union smb_search_close *io)
     823             : {
     824             :         struct smbcli_request *req;
     825             : 
     826           1 :         if (io->generic.level == RAW_FINDCLOSE_FCLOSE) {
     827           1 :                 return smb_raw_search_close_old(tree, io);
     828             :         }
     829             :         
     830           0 :         req = smbcli_request_setup(tree, SMBfindclose, 1, 0);
     831           0 :         if (!req) {
     832           0 :                 return NT_STATUS_NO_MEMORY;
     833             :         }
     834             : 
     835           0 :         SSVAL(req->out.vwv, VWV(0), io->findclose.in.handle);
     836             : 
     837           0 :         if (smbcli_request_send(req)) {
     838           0 :                 (void) smbcli_request_receive(req);
     839             :         }
     840             : 
     841           0 :         return smbcli_request_destroy(req);
     842             : }

Generated by: LCOV version 1.13