LCOV - code coverage report
Current view: top level - source4/libcli/raw - rawsearch.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 376 436 86.2 %
Date: 2021-09-23 10:06:22 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         592 : 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         592 :         if (req->in.data_size < 3 + count*43) {
      40           0 :                 req->status = NT_STATUS_INVALID_PARAMETER;
      41           0 :                 return;
      42             :         }
      43             :         
      44         592 :         p = req->in.data + 3;
      45             : 
      46       33975 :         for (i=0; i < count; i++) {
      47             :                 char *name;
      48             : 
      49       33383 :                 search_data.search.id.reserved      = CVAL(p, 0);
      50       33383 :                 memcpy(search_data.search.id.name,    p+1, 11);
      51       33383 :                 search_data.search.id.handle        = CVAL(p, 12);
      52       33383 :                 search_data.search.id.server_cookie = IVAL(p, 13);
      53       33383 :                 search_data.search.id.client_cookie = IVAL(p, 17);
      54       33383 :                 search_data.search.attrib           = CVAL(p, 21);
      55       38157 :                 search_data.search.write_time       = raw_pull_dos_date(req->transport,
      56       33383 :                                                                         p + 22);
      57       33383 :                 search_data.search.size             = IVAL(p, 26);
      58       33383 :                 smbcli_req_pull_ascii(&req->in.bufinfo, mem_ctx, &name, p+30, 13, STR_ASCII);
      59       33383 :                 search_data.search.name = name;
      60       33383 :                 if (!callback(private_data, &search_data)) {
      61           0 :                         break;
      62             :                 }
      63       33383 :                 p += 43;
      64             :         }
      65             : }
      66             : 
      67             : /****************************************************************************
      68             :  Old style search first.
      69             : ****************************************************************************/
      70         212 : 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         212 :         uint8_t op = SMBsearch;
      78             : 
      79         212 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
      80          14 :                 op = SMBffirst;
      81         198 :         } else if (io->generic.level == RAW_SEARCH_FUNIQUE) {
      82          14 :                 op = SMBfunique;
      83             :         }
      84             : 
      85         212 :         req = smbcli_request_setup(tree, op, 2, 0);
      86         212 :         if (!req) {
      87           0 :                 return NT_STATUS_NO_MEMORY;
      88             :         }
      89             :         
      90         212 :         SSVAL(req->out.vwv, VWV(0), io->search_first.in.max_count);
      91         212 :         SSVAL(req->out.vwv, VWV(1), io->search_first.in.search_attrib);
      92         212 :         smbcli_req_append_ascii4(req, io->search_first.in.pattern, STR_TERMINATE);
      93         212 :         smbcli_req_append_var_block(req, NULL, 0);
      94             : 
      95         393 :         if (!smbcli_request_send(req) || 
      96         212 :             !smbcli_request_receive(req)) {
      97           0 :                 return smbcli_request_destroy(req);
      98             :         }
      99             : 
     100         212 :         if (NT_STATUS_IS_OK(req->status)) {
     101         191 :                 io->search_first.out.count = SVAL(req->in.vwv, VWV(0));   
     102         191 :                 smb_raw_search_backend(req, mem_ctx, io->search_first.out.count, private_data, callback);
     103             :         }
     104             : 
     105         212 :         return smbcli_request_destroy(req);
     106             : }
     107             : 
     108             : /****************************************************************************
     109             :  Old style search next.
     110             : ****************************************************************************/
     111         401 : 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         401 :         uint8_t op = SMBsearch;
     120             : 
     121         401 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
     122           0 :                 op = SMBffirst;
     123             :         }
     124             :         
     125         401 :         req = smbcli_request_setup(tree, op, 2, 0);
     126         401 :         if (!req) {
     127           0 :                 return NT_STATUS_NO_MEMORY;
     128             :         }
     129             :         
     130         401 :         SSVAL(req->out.vwv, VWV(0), io->search_next.in.max_count);
     131         401 :         SSVAL(req->out.vwv, VWV(1), io->search_next.in.search_attrib);
     132         401 :         smbcli_req_append_ascii4(req, "", STR_TERMINATE);
     133             : 
     134         401 :         SCVAL(var_block,  0, io->search_next.in.id.reserved);
     135         401 :         memcpy(&var_block[1], io->search_next.in.id.name, 11);
     136         401 :         SCVAL(var_block, 12, io->search_next.in.id.handle);
     137         401 :         SIVAL(var_block, 13, io->search_next.in.id.server_cookie);
     138         401 :         SIVAL(var_block, 17, io->search_next.in.id.client_cookie);
     139             : 
     140         401 :         smbcli_req_append_var_block(req, var_block, 21);
     141             : 
     142         744 :         if (!smbcli_request_send(req) ||
     143         401 :             !smbcli_request_receive(req)) {
     144           0 :                 return smbcli_request_destroy(req);
     145             :         }
     146             : 
     147         401 :         if (NT_STATUS_IS_OK(req->status)) {
     148         401 :                 io->search_next.out.count = SVAL(req->in.vwv, VWV(0));
     149         401 :                 smb_raw_search_backend(req, mem_ctx, io->search_next.out.count, private_data, callback);
     150             :         }
     151             :         
     152         401 :         return smbcli_request_destroy(req);
     153             : }
     154             : 
     155             : 
     156             : /****************************************************************************
     157             :  Old style search next.
     158             : ****************************************************************************/
     159           7 : 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           7 :         req = smbcli_request_setup(tree, SMBfclose, 2, 0);
     166           7 :         if (!req) {
     167           0 :                 return NT_STATUS_NO_MEMORY;
     168             :         }
     169             :         
     170           7 :         SSVAL(req->out.vwv, VWV(0), io->fclose.in.max_count);
     171           7 :         SSVAL(req->out.vwv, VWV(1), io->fclose.in.search_attrib);
     172           7 :         smbcli_req_append_ascii4(req, "", STR_TERMINATE);
     173             : 
     174           7 :         SCVAL(var_block,  0, io->fclose.in.id.reserved);
     175           7 :         memcpy(&var_block[1], io->fclose.in.id.name, 11);
     176           7 :         SCVAL(var_block, 12, io->fclose.in.id.handle);
     177           7 :         SIVAL(var_block, 13, io->fclose.in.id.server_cookie);
     178           7 :         SIVAL(var_block, 17, io->fclose.in.id.client_cookie);
     179             : 
     180           7 :         smbcli_req_append_var_block(req, var_block, 21);
     181             : 
     182          13 :         if (!smbcli_request_send(req) ||
     183           7 :             !smbcli_request_receive(req)) {
     184           0 :                 return smbcli_request_destroy(req);
     185             :         }
     186             : 
     187           7 :         return smbcli_request_destroy(req);
     188             : }
     189             : 
     190             : 
     191             : 
     192             : /****************************************************************************
     193             :  Very raw search first - returns param/data blobs.
     194             : ****************************************************************************/
     195       11727 : 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       11727 :         uint16_t setup = TRANSACT2_FINDFIRST;
     203             :         NTSTATUS status;
     204             :         
     205       11727 :         tp.in.max_setup = 0;
     206       11727 :         tp.in.flags = 0; 
     207       11727 :         tp.in.timeout = 0;
     208       11727 :         tp.in.setup_count = 1;
     209       11727 :         tp.in.data = data_blob(NULL, 0);
     210       11727 :         tp.in.max_param = 10;
     211       11727 :         tp.in.max_data = 0xFFFF;
     212       11727 :         tp.in.setup = &setup;
     213             : 
     214       11727 :         if (io->t2ffirst.level != RAW_SEARCH_TRANS2) {
     215           0 :                 return NT_STATUS_INVALID_LEVEL;
     216             :         }
     217             : 
     218       11727 :         if (io->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) {
     219           0 :                 return NT_STATUS_INVALID_LEVEL;
     220             :         }
     221             : 
     222       11727 :         if (io->t2ffirst.data_level == RAW_SEARCH_DATA_EA_LIST) {
     223           7 :                 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       11727 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     232       11727 :         if (!tp.in.params.data) {
     233           0 :                 return NT_STATUS_NO_MEMORY;
     234             :         }
     235             : 
     236       11727 :         SSVAL(tp.in.params.data, 0, io->t2ffirst.in.search_attrib);
     237       11727 :         SSVAL(tp.in.params.data, 2, io->t2ffirst.in.max_count);      
     238       11727 :         SSVAL(tp.in.params.data, 4, io->t2ffirst.in.flags);
     239       11727 :         SSVAL(tp.in.params.data, 6, io->t2ffirst.data_level);
     240       11727 :         SIVAL(tp.in.params.data, 8, io->t2ffirst.in.storage_type);
     241             : 
     242       11727 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     243             :                                   io->t2ffirst.in.pattern, STR_TERMINATE);
     244             : 
     245       11727 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     246       11727 :         if (!NT_STATUS_IS_OK(status)) {
     247        2264 :                 return status;
     248             :         }
     249             : 
     250        9463 :         out_param_blob->length = tp.out.params.length;
     251        9463 :         out_param_blob->data = tp.out.params.data;
     252        9463 :         out_data_blob->length = tp.out.data.length;
     253        9463 :         out_data_blob->data = tp.out.data.data;
     254             : 
     255        9463 :         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        2044 : 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        2044 :         uint16_t setup = TRANSACT2_FINDNEXT;
     271             :         NTSTATUS status;
     272             :         
     273        2044 :         tp.in.max_setup = 0;
     274        2044 :         tp.in.flags = 0; 
     275        2044 :         tp.in.timeout = 0;
     276        2044 :         tp.in.setup_count = 1;
     277        2044 :         tp.in.data = data_blob(NULL, 0);
     278        2044 :         tp.in.max_param = 10;
     279        2044 :         tp.in.max_data = 0xFFFF;
     280        2044 :         tp.in.setup = &setup;
     281             : 
     282        2044 :         if (io->t2fnext.level != RAW_SEARCH_TRANS2) {
     283           0 :                 return NT_STATUS_INVALID_LEVEL;
     284             :         }
     285             : 
     286        2044 :         if (io->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {
     287           0 :                 return NT_STATUS_INVALID_LEVEL;
     288             :         }
     289             : 
     290        2044 :         if (io->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) {
     291           7 :                 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        2044 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     300        2044 :         if (!tp.in.params.data) {
     301           0 :                 return NT_STATUS_NO_MEMORY;
     302             :         }
     303             :         
     304        2044 :         SSVAL(tp.in.params.data, 0, io->t2fnext.in.handle);
     305        2044 :         SSVAL(tp.in.params.data, 2, io->t2fnext.in.max_count);
     306        2044 :         SSVAL(tp.in.params.data, 4, io->t2fnext.data_level);
     307        2044 :         SIVAL(tp.in.params.data, 6, io->t2fnext.in.resume_key);
     308        2044 :         SSVAL(tp.in.params.data, 10, io->t2fnext.in.flags);
     309             : 
     310        2044 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     311             :                                io->t2fnext.in.last_name,
     312             :                                STR_TERMINATE);
     313             : 
     314        2044 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     315        2044 :         if (!NT_STATUS_IS_OK(status)) {
     316           0 :                 return status;
     317             :         }
     318             : 
     319        2044 :         out_param_blob->length = tp.out.params.length;
     320        2044 :         out_param_blob->data = tp.out.params.data;
     321        2044 :         out_data_blob->length = tp.out.data.length;
     322        2044 :         out_data_blob->data = tp.out.data.data;
     323             : 
     324        2044 :         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      366478 : 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      366478 :         if (blob->length < 4) {
     342           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     343             :         }
     344             : 
     345      366478 :         *next_ofs = IVAL(blob->data, 0);
     346      366478 :         if (*next_ofs != 0) {
     347      349241 :                 blen = *next_ofs;
     348             :         } else {
     349       17052 :                 blen = blob->length;
     350             :         }
     351             : 
     352      366478 :         switch (level) {
     353       21776 :         case RAW_SEARCH_DATA_DIRECTORY_INFO:
     354       21776 :                 if (blen < 65) return NT_STATUS_INFO_LENGTH_MISMATCH;
     355       21776 :                 data->directory_info.file_index  = IVAL(blob->data,             4);
     356       21776 :                 data->directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     357       21776 :                 data->directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     358       21776 :                 data->directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     359       21776 :                 data->directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     360       21776 :                 data->directory_info.size        = BVAL(blob->data,            40);
     361       21776 :                 data->directory_info.alloc_size  = BVAL(blob->data,            48);
     362       21776 :                 data->directory_info.attrib      = IVAL(blob->data,            56);
     363       21776 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     364             :                                               &data->directory_info.name,
     365             :                                               60, 64, str_flags);
     366       21776 :                 if (*next_ofs != 0 && *next_ofs < 64+len) {
     367           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     368             :                 }
     369       21776 :                 return NT_STATUS_OK;
     370             : 
     371       22484 :         case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
     372       22484 :                 if (blen < 69) return NT_STATUS_INFO_LENGTH_MISMATCH;
     373       22484 :                 data->full_directory_info.file_index  = IVAL(blob->data,                4);
     374       22484 :                 data->full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     375       22484 :                 data->full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     376       22484 :                 data->full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     377       22484 :                 data->full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     378       22484 :                 data->full_directory_info.size        = BVAL(blob->data,               40);
     379       22484 :                 data->full_directory_info.alloc_size  = BVAL(blob->data,               48);
     380       22484 :                 data->full_directory_info.attrib      = IVAL(blob->data,               56);
     381       22484 :                 data->full_directory_info.ea_size     = IVAL(blob->data,               64);
     382       22484 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     383             :                                               &data->full_directory_info.name,
     384             :                                               60, 68, str_flags);
     385       22484 :                 if (*next_ofs != 0 && *next_ofs < 68+len) {
     386           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     387             :                 }
     388       22484 :                 return NT_STATUS_OK;
     389             : 
     390      212865 :         case RAW_SEARCH_DATA_NAME_INFO:
     391      212865 :                 if (blen < 13) return NT_STATUS_INFO_LENGTH_MISMATCH;
     392      212865 :                 data->name_info.file_index  = IVAL(blob->data, 4);
     393      212865 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     394             :                                               &data->name_info.name,
     395             :                                               8, 12, str_flags);
     396      212865 :                 if (*next_ofs != 0 && *next_ofs < 12+len) {
     397           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     398             :                 }
     399      212865 :                 return NT_STATUS_OK;
     400             : 
     401             : 
     402       65707 :         case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
     403       65707 :                 if (blen < 95) return NT_STATUS_INFO_LENGTH_MISMATCH;
     404       65707 :                 data->both_directory_info.file_index  = IVAL(blob->data,                4);
     405       65707 :                 data->both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     406       65707 :                 data->both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     407       65707 :                 data->both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     408       65707 :                 data->both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     409       65707 :                 data->both_directory_info.size        = BVAL(blob->data,               40);
     410       65707 :                 data->both_directory_info.alloc_size  = BVAL(blob->data,               48);
     411       65707 :                 data->both_directory_info.attrib      = IVAL(blob->data,               56);
     412       65707 :                 data->both_directory_info.ea_size     = IVAL(blob->data,               64);
     413       65707 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     414             :                                         &data->both_directory_info.short_name,
     415             :                                         68, 70, STR_LEN8BIT | STR_UNICODE);
     416       65707 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     417             :                                               &data->both_directory_info.name,
     418             :                                               60, 94, str_flags);
     419       65707 :                 if (*next_ofs != 0 && *next_ofs < 94+len) {
     420           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     421             :                 }
     422       65707 :                 return NT_STATUS_OK;
     423             : 
     424             : 
     425       21740 :         case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
     426       21740 :                 if (blen < 81) return NT_STATUS_INFO_LENGTH_MISMATCH;
     427       21740 :                 data->id_full_directory_info.file_index  = IVAL(blob->data,             4);
     428       21740 :                 data->id_full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     429       21740 :                 data->id_full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     430       21740 :                 data->id_full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     431       21740 :                 data->id_full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     432       21740 :                 data->id_full_directory_info.size        = BVAL(blob->data,            40);
     433       21740 :                 data->id_full_directory_info.alloc_size  = BVAL(blob->data,            48);
     434       21740 :                 data->id_full_directory_info.attrib      = IVAL(blob->data,            56);
     435       21740 :                 data->id_full_directory_info.ea_size     = IVAL(blob->data,            64);
     436       21740 :                 data->id_full_directory_info.file_id     = BVAL(blob->data,            72);
     437       21740 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     438             :                                               &data->id_full_directory_info.name,
     439             :                                               60, 80, str_flags);
     440       21740 :                 if (*next_ofs != 0 && *next_ofs < 80+len) {
     441           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     442             :                 }
     443       21740 :                 return NT_STATUS_OK;
     444             : 
     445       21906 :         case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
     446       21906 :                 if (blen < 105) return NT_STATUS_INFO_LENGTH_MISMATCH;
     447       21906 :                 data->id_both_directory_info.file_index  = IVAL(blob->data,             4);
     448       21906 :                 data->id_both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     449       21906 :                 data->id_both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     450       21906 :                 data->id_both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     451       21906 :                 data->id_both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     452       21906 :                 data->id_both_directory_info.size        = BVAL(blob->data,            40);
     453       21906 :                 data->id_both_directory_info.alloc_size  = BVAL(blob->data,            48);
     454       21906 :                 data->id_both_directory_info.attrib      = SVAL(blob->data,            56);
     455       21906 :                 data->id_both_directory_info.ea_size     = IVAL(blob->data,            64);
     456       21906 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     457             :                                      &data->id_both_directory_info.short_name,
     458             :                                      68, 70, STR_LEN8BIT | STR_UNICODE);
     459       21906 :                 memcpy(data->id_both_directory_info.short_name_buf, blob->data + 70, 24);
     460       21906 :                 data->id_both_directory_info.file_id     = BVAL(blob->data,            96);
     461       21906 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     462             :                                               &data->id_both_directory_info.name,
     463             :                                               60, 104, str_flags);
     464       21906 :                 if (*next_ofs != 0 && *next_ofs < 104+len) {
     465           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     466             :                 }
     467       21906 :                 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      220709 : 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      220709 :         switch (level) {
     497           0 :         case RAW_SEARCH_DATA_GENERIC:
     498             :         case RAW_SEARCH_DATA_SEARCH:
     499             :                 /* handled elsewhere */
     500           0 :                 return -1;
     501             : 
     502       10522 :         case RAW_SEARCH_DATA_STANDARD:
     503       10522 :                 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       10522 :                 if (blob->length < 24) return -1;
     510       11930 :                 data->standard.create_time = raw_pull_dos_date2(tree->session->transport,
     511       10522 :                                                                 blob->data + 0);
     512       11930 :                 data->standard.access_time = raw_pull_dos_date2(tree->session->transport,
     513       10522 :                                                                 blob->data + 4);
     514       11930 :                 data->standard.write_time  = raw_pull_dos_date2(tree->session->transport,
     515       10522 :                                                                 blob->data + 8);
     516       10522 :                 data->standard.size        = IVAL(blob->data, 12);
     517       10522 :                 data->standard.alloc_size  = IVAL(blob->data, 16);
     518       10522 :                 data->standard.attrib      = SVAL(blob->data, 20);
     519       10522 :                 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       10522 :                 return len + 23;
     523             : 
     524      124608 :         case RAW_SEARCH_DATA_EA_SIZE:
     525      124608 :                 if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
     526      114800 :                         if (blob->length < 4) return -1;
     527      114800 :                         data->ea_size.resume_key = IVAL(blob->data, 0);
     528      114800 :                         blob->data += 4;
     529      114800 :                         blob->length -= 4;
     530             :                 }
     531      124608 :                 if (blob->length < 28) return -1;
     532      142309 :                 data->ea_size.create_time = raw_pull_dos_date2(tree->session->transport,
     533      124608 :                                                                blob->data + 0);
     534      142309 :                 data->ea_size.access_time = raw_pull_dos_date2(tree->session->transport,
     535      124608 :                                                                blob->data + 4);
     536      142309 :                 data->ea_size.write_time  = raw_pull_dos_date2(tree->session->transport,
     537      124608 :                                                                blob->data + 8);
     538      124608 :                 data->ea_size.size        = IVAL(blob->data, 12);
     539      124608 :                 data->ea_size.alloc_size  = IVAL(blob->data, 16);
     540      124608 :                 data->ea_size.attrib      = SVAL(blob->data, 20);
     541      124608 :                 data->ea_size.ea_size     = IVAL(blob->data, 22);
     542      124608 :                 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      124608 :                 return len + 27 + 1;
     546             : 
     547          21 :         case RAW_SEARCH_DATA_EA_LIST:
     548          21 :                 if (flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
     549          21 :                         if (blob->length < 4) return -1;
     550          21 :                         data->ea_list.resume_key = IVAL(blob->data, 0);
     551          21 :                         blob->data += 4;
     552          21 :                         blob->length -= 4;
     553             :                 }
     554          21 :                 if (blob->length < 28) return -1;
     555          24 :                 data->ea_list.create_time = raw_pull_dos_date2(tree->session->transport,
     556          21 :                                                                blob->data + 0);
     557          24 :                 data->ea_list.access_time = raw_pull_dos_date2(tree->session->transport,
     558          21 :                                                                blob->data + 4);
     559          24 :                 data->ea_list.write_time  = raw_pull_dos_date2(tree->session->transport,
     560          21 :                                                                blob->data + 8);
     561          21 :                 data->ea_list.size        = IVAL(blob->data, 12);
     562          21 :                 data->ea_list.alloc_size  = IVAL(blob->data, 16);
     563          21 :                 data->ea_list.attrib      = SVAL(blob->data, 20);
     564          21 :                 ea_size                   = IVAL(blob->data, 22);
     565          21 :                 if (ea_size > 0xFFFF) {
     566           0 :                         return -1;
     567             :                 }
     568          21 :                 eablob.data = blob->data + 22;
     569          21 :                 eablob.length = ea_size;
     570          21 :                 if (eablob.length > blob->length - 24) {
     571           0 :                         return -1;
     572             :                 }
     573          21 :                 status = ea_pull_list(&eablob, mem_ctx, 
     574             :                                       &data->ea_list.eas.num_eas,
     575             :                                       &data->ea_list.eas.eas);
     576          21 :                 if (!NT_STATUS_IS_OK(status)) {
     577           0 :                         return -1;
     578             :                 }
     579          42 :                 len = smbcli_blob_pull_string(tree->session, mem_ctx, blob,
     580             :                                               &data->ea_list.name,
     581          39 :                                               22+ea_size, 23+ea_size, 
     582             :                                               STR_LEN8BIT | STR_NOALIGN);
     583          21 :                 return len + ea_size + 23 + 1;
     584             : 
     585           6 :         case RAW_SEARCH_DATA_UNIX_INFO:
     586           6 :                 if (blob->length < 109) return -1;
     587           6 :                 ofs                                  = IVAL(blob->data,             0);
     588           6 :                 data->unix_info.file_index           = IVAL(blob->data,             4);
     589           6 :                 data->unix_info.size                 = BVAL(blob->data,             8);
     590           6 :                 data->unix_info.alloc_size           = BVAL(blob->data,            16);
     591           6 :                 data->unix_info.status_change_time   = smbcli_pull_nttime(blob->data, 24);
     592           6 :                 data->unix_info.access_time          = smbcli_pull_nttime(blob->data, 32);
     593           6 :                 data->unix_info.change_time          = smbcli_pull_nttime(blob->data, 40);
     594           6 :                 data->unix_info.uid                  = IVAL(blob->data,            48);
     595           6 :                 data->unix_info.gid                  = IVAL(blob->data,            56);
     596           6 :                 data->unix_info.file_type            = IVAL(blob->data,            64);
     597           6 :                 data->unix_info.dev_major            = BVAL(blob->data,            68);
     598           6 :                 data->unix_info.dev_minor            = BVAL(blob->data,            76);
     599           6 :                 data->unix_info.unique_id            = BVAL(blob->data,            84);
     600           6 :                 data->unix_info.permissions          = IVAL(blob->data,            92);
     601           6 :                 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           6 :                 len = smbcli_blob_pull_unix_string(tree->session, mem_ctx, blob,
     604             :                                            &data->unix_info.name, 108, 0);
     605           6 :                 if (ofs != 0 && ofs < 108+len) {
     606           0 :                         return -1;
     607             :                 }
     608           6 :                 return ofs;
     609             : 
     610           4 :         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           4 :                 if (blob->length < (116 + 8 + 4 + 2)) {
     617           0 :                         return -1;
     618             :                 }
     619             : 
     620           4 :                 ofs                                 = IVAL(blob->data,   0);
     621           4 :                 data->unix_info2.file_index         = IVAL(blob->data,   4);
     622           4 :                 data->unix_info2.end_of_file        = BVAL(blob->data,   8);
     623           4 :                 data->unix_info2.num_bytes          = BVAL(blob->data,  16);
     624           4 :                 data->unix_info2.status_change_time = smbcli_pull_nttime(blob->data, 24);
     625           4 :                 data->unix_info2.access_time        = smbcli_pull_nttime(blob->data, 32);
     626           4 :                 data->unix_info2.change_time        = smbcli_pull_nttime(blob->data, 40);
     627           4 :                 data->unix_info2.uid                = IVAL(blob->data,  48);
     628           4 :                 data->unix_info2.gid                = IVAL(blob->data,  56);
     629           4 :                 data->unix_info2.file_type          = IVAL(blob->data,  64);
     630           4 :                 data->unix_info2.dev_major          = BVAL(blob->data,  68);
     631           4 :                 data->unix_info2.dev_minor          = BVAL(blob->data,  76);
     632           4 :                 data->unix_info2.unique_id          = BVAL(blob->data,  84);
     633           4 :                 data->unix_info2.permissions        = IVAL(blob->data,  92);
     634           4 :                 data->unix_info2.nlink              = IVAL(blob->data, 100);
     635           4 :                 data->unix_info2.create_time     = smbcli_pull_nttime(blob->data, 108);
     636           4 :                 data->unix_info2.file_flags      = IVAL(blob->data, 116);
     637           4 :                 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           4 :                 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           4 :                 if (ofs != 0 && ofs < (8 + 116 + 4 + len)) {
     649           0 :                         return -1;
     650             :                 }
     651             : 
     652           4 :                 return ofs;
     653             : 
     654       85548 :                 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       85548 :                         unsigned int str_flags = STR_UNICODE;
     661       85548 :                         if (!(tree->session->transport->negotiate.capabilities & CAP_UNICODE)) {
     662           0 :                                 str_flags = STR_ASCII;
     663             :                         }
     664             :                         
     665       85548 :                 status = smb_raw_search_common(mem_ctx, level, blob, data, &ofs, str_flags);
     666       85548 :                 if (!NT_STATUS_IS_OK(status)) {
     667           0 :                         return -1;
     668             :                 }
     669       85548 :                 return ofs;
     670             :         }
     671             :         }
     672             : 
     673             :         /* invalid level */
     674           0 :         return -1;
     675             : }
     676             : 
     677             : /****************************************************************************
     678             :  Trans2 search backend - process output.
     679             : ****************************************************************************/
     680       11507 : 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       11507 :         blob2.data = blob->data;
     694       11507 :         blob2.length = blob->length;
     695             : 
     696      432315 :         for (i=0; i < count; i++) {
     697             :                 union smb_search_data search_data;
     698             :                 unsigned int len;
     699             : 
     700      220709 :                 len = parse_trans2_search(tree, mem_ctx, level, flags, &blob2, &search_data);
     701      220709 :                 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      220709 :                 if (!callback(private_data, &search_data)) {
     708           0 :                         break;
     709             :                 }
     710             : 
     711      220709 :                 if (len == 0) break;
     712             : 
     713      220709 :                 blob2.data += len;
     714      220709 :                 blob2.length -= len;
     715             :         }
     716             : 
     717       11507 :         return NT_STATUS_OK;
     718             : }
     719             : 
     720             : 
     721             : /* Implements trans2findfirst2 and old search
     722             :  */
     723       11939 : _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       11939 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     729             :         NTSTATUS status;
     730             : 
     731       11939 :         switch (io->generic.level) {
     732         212 :         case RAW_SEARCH_SEARCH:
     733             :         case RAW_SEARCH_FFIRST:
     734             :         case RAW_SEARCH_FUNIQUE:
     735         212 :                 return smb_raw_search_first_old(tree, mem_ctx, io, private_data, callback);
     736             : 
     737       11595 :         case RAW_SEARCH_TRANS2:
     738       11595 :                 break;
     739             : 
     740           0 :         case RAW_SEARCH_SMB2:
     741           0 :                 return NT_STATUS_INVALID_LEVEL;
     742             :         }
     743             : 
     744       11727 :         status = smb_raw_search_first_blob(tree, mem_ctx,
     745             :                                            io, &p_blob, &d_blob);
     746       11727 :         if (!NT_STATUS_IS_OK(status)) {
     747        2264 :                 return status;
     748             :         }
     749             :         
     750        9463 :         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        9463 :         io->t2ffirst.out.handle = SVAL(p_blob.data, 0);
     758        9463 :         io->t2ffirst.out.count = SVAL(p_blob.data, 2);
     759        9463 :         io->t2ffirst.out.end_of_search = SVAL(p_blob.data, 4);
     760             : 
     761       17676 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     762             :                                           io->generic.data_level, 
     763       17544 :                                           io->t2ffirst.in.flags, io->t2ffirst.out.count,
     764             :                                           &d_blob, private_data, callback);
     765             :         
     766        9463 :         return status;
     767             : }
     768             : 
     769             : /* Implements trans2findnext2 and old smbsearch
     770             :  */
     771        2445 : 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        2445 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     777             :         NTSTATUS status;
     778             : 
     779        2445 :         switch (io->generic.level) {
     780         401 :         case RAW_SEARCH_SEARCH:
     781             :         case RAW_SEARCH_FFIRST:
     782         401 :                 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        2044 :         case RAW_SEARCH_TRANS2:
     788        2044 :                 break;
     789             : 
     790           0 :         case RAW_SEARCH_SMB2:
     791           0 :                 return NT_STATUS_INVALID_LEVEL;
     792             :         }
     793             : 
     794        2044 :         status = smb_raw_search_next_blob(tree, mem_ctx,
     795             :                                           io, &p_blob, &d_blob);
     796        2044 :         if (!NT_STATUS_IS_OK(status)) {
     797           0 :                 return status;
     798             :         }
     799             :         
     800        2044 :         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        2044 :         io->t2fnext.out.count = SVAL(p_blob.data, 0);
     808        2044 :         io->t2fnext.out.end_of_search = SVAL(p_blob.data, 2);
     809             :                 
     810        3803 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     811             :                                           io->generic.data_level, 
     812        3803 :                                           io->t2fnext.in.flags, io->t2fnext.out.count,
     813             :                                           &d_blob, private_data, callback);
     814             :         
     815        2044 :         return status;
     816             : }
     817             : 
     818             : /* 
     819             :    Implements trans2findclose2
     820             :  */
     821           7 : NTSTATUS smb_raw_search_close(struct smbcli_tree *tree,
     822             :                               union smb_search_close *io)
     823             : {
     824             :         struct smbcli_request *req;
     825             : 
     826           7 :         if (io->generic.level == RAW_FINDCLOSE_FCLOSE) {
     827           7 :                 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