LCOV - code coverage report
Current view: top level - source4/libcli/raw - rawsearch.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 388 461 84.2 %
Date: 2024-04-21 15:09:00 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         588 : 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           0 :         union smb_search_data search_data;
      36           0 :         int i;
      37           0 :         uint8_t *p;
      38             : 
      39         588 :         if (req->in.data_size < 3 + count*43) {
      40           0 :                 req->status = NT_STATUS_INVALID_PARAMETER;
      41           0 :                 return;
      42             :         }
      43             : 
      44         588 :         p = req->in.data + 3;
      45             : 
      46       33957 :         for (i=0; i < count; i++) {
      47           0 :                 char *name;
      48             : 
      49       33369 :                 search_data.search.id.reserved      = CVAL(p, 0);
      50       33369 :                 memcpy(search_data.search.id.name,    p+1, 11);
      51       33369 :                 search_data.search.id.handle        = CVAL(p, 12);
      52       33369 :                 search_data.search.id.server_cookie = IVAL(p, 13);
      53       33369 :                 search_data.search.id.client_cookie = IVAL(p, 17);
      54       33369 :                 search_data.search.attrib           = CVAL(p, 21);
      55       66738 :                 search_data.search.write_time       = raw_pull_dos_date(req->transport,
      56       33369 :                                                                         p + 22);
      57       33369 :                 search_data.search.size             = IVAL(p, 26);
      58       33369 :                 smbcli_req_pull_ascii(&req->in.bufinfo, mem_ctx, &name, p+30, 13, STR_ASCII);
      59       33369 :                 search_data.search.name = name;
      60       33369 :                 if (!callback(private_data, &search_data)) {
      61           0 :                         break;
      62             :                 }
      63       33369 :                 p += 43;
      64             :         }
      65             : }
      66             : 
      67             : /****************************************************************************
      68             :  Old style search first.
      69             : ****************************************************************************/
      70         210 : 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           0 :         struct smbcli_request *req;
      77         210 :         uint8_t op = SMBsearch;
      78             : 
      79         210 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
      80          14 :                 op = SMBffirst;
      81         196 :         } else if (io->generic.level == RAW_SEARCH_FUNIQUE) {
      82          14 :                 op = SMBfunique;
      83             :         }
      84             : 
      85         210 :         req = smbcli_request_setup(tree, op, 2, 0);
      86         210 :         if (!req) {
      87           0 :                 return NT_STATUS_NO_MEMORY;
      88             :         }
      89             : 
      90         210 :         SSVAL(req->out.vwv, VWV(0), io->search_first.in.max_count);
      91         210 :         SSVAL(req->out.vwv, VWV(1), io->search_first.in.search_attrib);
      92         210 :         smbcli_req_append_ascii4(req, io->search_first.in.pattern, STR_TERMINATE);
      93         210 :         smbcli_req_append_var_block(req, NULL, 0);
      94             : 
      95         210 :         if (!smbcli_request_send(req) ||
      96         210 :             !smbcli_request_receive(req)) {
      97           0 :                 return smbcli_request_destroy(req);
      98             :         }
      99             : 
     100         210 :         if (NT_STATUS_IS_OK(req->status)) {
     101         189 :                 io->search_first.out.count = SVAL(req->in.vwv, VWV(0));
     102         189 :                 smb_raw_search_backend(req, mem_ctx, io->search_first.out.count, private_data, callback);
     103             :         }
     104             : 
     105         210 :         return smbcli_request_destroy(req);
     106             : }
     107             : 
     108             : /****************************************************************************
     109             :  Old style search next.
     110             : ****************************************************************************/
     111         399 : 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           0 :         struct smbcli_request *req;
     118           0 :         uint8_t var_block[21];
     119         399 :         uint8_t op = SMBsearch;
     120             : 
     121         399 :         if (io->generic.level == RAW_SEARCH_FFIRST) {
     122           0 :                 op = SMBffirst;
     123             :         }
     124             : 
     125         399 :         req = smbcli_request_setup(tree, op, 2, 0);
     126         399 :         if (!req) {
     127           0 :                 return NT_STATUS_NO_MEMORY;
     128             :         }
     129             : 
     130         399 :         SSVAL(req->out.vwv, VWV(0), io->search_next.in.max_count);
     131         399 :         SSVAL(req->out.vwv, VWV(1), io->search_next.in.search_attrib);
     132         399 :         smbcli_req_append_ascii4(req, "", STR_TERMINATE);
     133             : 
     134         399 :         SCVAL(var_block,  0, io->search_next.in.id.reserved);
     135         399 :         memcpy(&var_block[1], io->search_next.in.id.name, 11);
     136         399 :         SCVAL(var_block, 12, io->search_next.in.id.handle);
     137         399 :         SIVAL(var_block, 13, io->search_next.in.id.server_cookie);
     138         399 :         SIVAL(var_block, 17, io->search_next.in.id.client_cookie);
     139             : 
     140         399 :         smbcli_req_append_var_block(req, var_block, 21);
     141             : 
     142         399 :         if (!smbcli_request_send(req) ||
     143         399 :             !smbcli_request_receive(req)) {
     144           0 :                 return smbcli_request_destroy(req);
     145             :         }
     146             : 
     147         399 :         if (NT_STATUS_IS_OK(req->status)) {
     148         399 :                 io->search_next.out.count = SVAL(req->in.vwv, VWV(0));
     149         399 :                 smb_raw_search_backend(req, mem_ctx, io->search_next.out.count, private_data, callback);
     150             :         }
     151             : 
     152         399 :         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           0 :         struct smbcli_request *req;
     163           0 :         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           7 :         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       12722 : 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         175 :         struct smb_trans2 tp;
     202       12722 :         uint16_t setup = TRANSACT2_FINDFIRST;
     203         175 :         NTSTATUS status;
     204             : 
     205       12722 :         tp.in.max_setup = 0;
     206       12722 :         tp.in.flags = 0;
     207       12722 :         tp.in.timeout = 0;
     208       12722 :         tp.in.setup_count = 1;
     209       12722 :         tp.in.data = data_blob(NULL, 0);
     210       12722 :         tp.in.max_param = 10;
     211       12722 :         tp.in.max_data = 0xFFFF;
     212       12722 :         tp.in.setup = &setup;
     213             : 
     214       12722 :         if (io->t2ffirst.level != RAW_SEARCH_TRANS2) {
     215           0 :                 return NT_STATUS_INVALID_LEVEL;
     216             :         }
     217             : 
     218       12722 :         if (io->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) {
     219           0 :                 return NT_STATUS_INVALID_LEVEL;
     220             :         }
     221             : 
     222       12722 :         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       12722 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     232       12722 :         if (!tp.in.params.data) {
     233           0 :                 return NT_STATUS_NO_MEMORY;
     234             :         }
     235             : 
     236       12722 :         SSVAL(tp.in.params.data, 0, io->t2ffirst.in.search_attrib);
     237       12722 :         SSVAL(tp.in.params.data, 2, io->t2ffirst.in.max_count);
     238       12722 :         SSVAL(tp.in.params.data, 4, io->t2ffirst.in.flags);
     239       12722 :         SSVAL(tp.in.params.data, 6, io->t2ffirst.data_level);
     240       12722 :         SIVAL(tp.in.params.data, 8, io->t2ffirst.in.storage_type);
     241             : 
     242       12722 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     243             :                                   io->t2ffirst.in.pattern, STR_TERMINATE);
     244             : 
     245       12722 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     246       12722 :         if (!NT_STATUS_IS_OK(status)) {
     247        2715 :                 return status;
     248             :         }
     249             : 
     250       10007 :         out_param_blob->length = tp.out.params.length;
     251       10007 :         out_param_blob->data = tp.out.params.data;
     252       10007 :         out_data_blob->length = tp.out.data.length;
     253       10007 :         out_data_blob->data = tp.out.data.data;
     254             : 
     255       10007 :         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        2065 : 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           0 :         struct smb_trans2 tp;
     270        2065 :         uint16_t setup = TRANSACT2_FINDNEXT;
     271           0 :         NTSTATUS status;
     272             : 
     273        2065 :         tp.in.max_setup = 0;
     274        2065 :         tp.in.flags = 0;
     275        2065 :         tp.in.timeout = 0;
     276        2065 :         tp.in.setup_count = 1;
     277        2065 :         tp.in.data = data_blob(NULL, 0);
     278        2065 :         tp.in.max_param = 10;
     279        2065 :         tp.in.max_data = 0xFFFF;
     280        2065 :         tp.in.setup = &setup;
     281             : 
     282        2065 :         if (io->t2fnext.level != RAW_SEARCH_TRANS2) {
     283           0 :                 return NT_STATUS_INVALID_LEVEL;
     284             :         }
     285             : 
     286        2065 :         if (io->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {
     287           0 :                 return NT_STATUS_INVALID_LEVEL;
     288             :         }
     289             : 
     290        2065 :         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        2065 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 12);
     300        2065 :         if (!tp.in.params.data) {
     301           0 :                 return NT_STATUS_NO_MEMORY;
     302             :         }
     303             : 
     304        2065 :         SSVAL(tp.in.params.data, 0, io->t2fnext.in.handle);
     305        2065 :         SSVAL(tp.in.params.data, 2, io->t2fnext.in.max_count);
     306        2065 :         SSVAL(tp.in.params.data, 4, io->t2fnext.data_level);
     307        2065 :         SIVAL(tp.in.params.data, 6, io->t2fnext.in.resume_key);
     308        2065 :         SSVAL(tp.in.params.data, 10, io->t2fnext.in.flags);
     309             : 
     310        2065 :         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
     311             :                                io->t2fnext.in.last_name,
     312             :                                STR_TERMINATE);
     313             : 
     314        2065 :         status = smb_raw_trans2(tree, mem_ctx, &tp);
     315        2065 :         if (!NT_STATUS_IS_OK(status)) {
     316           0 :                 return status;
     317             :         }
     318             : 
     319        2065 :         out_param_blob->length = tp.out.params.length;
     320        2065 :         out_param_blob->data = tp.out.params.data;
     321        2065 :         out_data_blob->length = tp.out.data.length;
     322        2065 :         out_data_blob->data = tp.out.data.data;
     323             : 
     324        2065 :         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      768433 : 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         227 :         unsigned int len, blen;
     340             : 
     341      768433 :         if (blob->length < 4) {
     342           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     343             :         }
     344             : 
     345      768433 :         *next_ofs = IVAL(blob->data, 0);
     346      768433 :         if (*next_ofs != 0) {
     347      764933 :                 blen = *next_ofs;
     348             :         } else {
     349        3275 :                 blen = blob->length;
     350             :         }
     351             : 
     352      768433 :         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      423284 :         case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
     372      423284 :                 if (blen < 69) return NT_STATUS_INFO_LENGTH_MISMATCH;
     373      423284 :                 data->full_directory_info.file_index  = IVAL(blob->data,                4);
     374      423284 :                 data->full_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     375      423284 :                 data->full_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     376      423284 :                 data->full_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     377      423284 :                 data->full_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     378      423284 :                 data->full_directory_info.size        = BVAL(blob->data,               40);
     379      423284 :                 data->full_directory_info.alloc_size  = BVAL(blob->data,               48);
     380      423284 :                 data->full_directory_info.attrib      = IVAL(blob->data,               56);
     381      423284 :                 data->full_directory_info.ea_size     = IVAL(blob->data,               64);
     382      423284 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     383             :                                               &data->full_directory_info.name,
     384             :                                               60, 68, str_flags);
     385      423284 :                 if (*next_ofs != 0 && *next_ofs < 68+len) {
     386           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     387             :                 }
     388      423284 :                 return NT_STATUS_OK;
     389             : 
     390      197820 :         case RAW_SEARCH_DATA_NAME_INFO:
     391      197820 :                 if (blen < 13) return NT_STATUS_INFO_LENGTH_MISMATCH;
     392      197820 :                 data->name_info.file_index  = IVAL(blob->data, 4);
     393      197820 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     394             :                                               &data->name_info.name,
     395             :                                               8, 12, str_flags);
     396      197820 :                 if (*next_ofs != 0 && *next_ofs < 12+len) {
     397           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     398             :                 }
     399      197820 :                 return NT_STATUS_OK;
     400             : 
     401             : 
     402       81901 :         case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
     403       81901 :                 if (blen < 95) return NT_STATUS_INFO_LENGTH_MISMATCH;
     404       81901 :                 data->both_directory_info.file_index  = IVAL(blob->data,                4);
     405       81901 :                 data->both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     406       81901 :                 data->both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     407       81901 :                 data->both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     408       81901 :                 data->both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     409       81901 :                 data->both_directory_info.size        = BVAL(blob->data,               40);
     410       81901 :                 data->both_directory_info.alloc_size  = BVAL(blob->data,               48);
     411       81901 :                 data->both_directory_info.attrib      = IVAL(blob->data,               56);
     412       81901 :                 data->both_directory_info.ea_size     = IVAL(blob->data,               64);
     413       81901 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     414             :                                         &data->both_directory_info.short_name,
     415             :                                         68, 70, STR_LEN8BIT | STR_UNICODE);
     416       81901 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     417             :                                               &data->both_directory_info.name,
     418             :                                               60, 94, str_flags);
     419       81901 :                 if (*next_ofs != 0 && *next_ofs < 94+len) {
     420           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     421             :                 }
     422       81901 :                 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       21912 :         case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
     446       21912 :                 if (blen < 105) return NT_STATUS_INFO_LENGTH_MISMATCH;
     447       21912 :                 data->id_both_directory_info.file_index  = IVAL(blob->data,             4);
     448       21912 :                 data->id_both_directory_info.create_time = smbcli_pull_nttime(blob->data,  8);
     449       21912 :                 data->id_both_directory_info.access_time = smbcli_pull_nttime(blob->data, 16);
     450       21912 :                 data->id_both_directory_info.write_time  = smbcli_pull_nttime(blob->data, 24);
     451       21912 :                 data->id_both_directory_info.change_time = smbcli_pull_nttime(blob->data, 32);
     452       21912 :                 data->id_both_directory_info.size        = BVAL(blob->data,            40);
     453       21912 :                 data->id_both_directory_info.alloc_size  = BVAL(blob->data,            48);
     454       21912 :                 data->id_both_directory_info.attrib      = SVAL(blob->data,            56);
     455       21912 :                 data->id_both_directory_info.ea_size     = IVAL(blob->data,            64);
     456       21912 :                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
     457             :                                      &data->id_both_directory_info.short_name,
     458             :                                      68, 70, STR_LEN8BIT | STR_UNICODE);
     459       21912 :                 memcpy(data->id_both_directory_info.short_name_buf, blob->data + 70, 24);
     460       21912 :                 data->id_both_directory_info.file_id     = BVAL(blob->data,            96);
     461       21912 :                 len = smbcli_blob_pull_string(NULL, mem_ctx, blob,
     462             :                                               &data->id_both_directory_info.name,
     463             :                                               60, 104, str_flags);
     464       21912 :                 if (*next_ofs != 0 && *next_ofs < 104+len) {
     465           0 :                         return NT_STATUS_INFO_LENGTH_MISMATCH;
     466             :                 }
     467       21912 :                 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      236867 : 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         221 :         unsigned int len, ofs;
     492         221 :         uint32_t ea_size;
     493         221 :         DATA_BLOB eablob;
     494         221 :         NTSTATUS status;
     495             : 
     496      236867 :         switch (level) {
     497           0 :         case RAW_SEARCH_DATA_GENERIC:
     498             :         case RAW_SEARCH_DATA_SEARCH:
     499             :                 /* handled elsewhere */
     500           0 :                 return -1;
     501             : 
     502       10508 :         case RAW_SEARCH_DATA_STANDARD:
     503       10508 :                 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       10508 :                 if (blob->length < 24) return -1;
     510       21016 :                 data->standard.create_time = raw_pull_dos_date2(tree->session->transport,
     511       10508 :                                                                 blob->data + 0);
     512       21016 :                 data->standard.access_time = raw_pull_dos_date2(tree->session->transport,
     513       10508 :                                                                 blob->data + 4);
     514       21016 :                 data->standard.write_time  = raw_pull_dos_date2(tree->session->transport,
     515       10508 :                                                                 blob->data + 8);
     516       10508 :                 data->standard.size        = IVAL(blob->data, 12);
     517       10508 :                 data->standard.alloc_size  = IVAL(blob->data, 16);
     518       10508 :                 data->standard.attrib      = SVAL(blob->data, 20);
     519       10508 :                 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       10508 :                 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      249216 :                 data->ea_size.create_time = raw_pull_dos_date2(tree->session->transport,
     533      124608 :                                                                blob->data + 0);
     534      249216 :                 data->ea_size.access_time = raw_pull_dos_date2(tree->session->transport,
     535      124608 :                                                                blob->data + 4);
     536      249216 :                 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          42 :                 data->ea_list.create_time = raw_pull_dos_date2(tree->session->transport,
     556          21 :                                                                blob->data + 0);
     557          42 :                 data->ea_list.access_time = raw_pull_dos_date2(tree->session->transport,
     558          21 :                                                                blob->data + 4);
     559          42 :                 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          21 :                                               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      101720 :                 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      101720 :                         unsigned int str_flags = STR_UNICODE;
     661      101720 :                         if (!(tree->session->transport->negotiate.capabilities & CAP_UNICODE)) {
     662           0 :                                 str_flags = STR_ASCII;
     663             :                         }
     664             : 
     665      101720 :                 status = smb_raw_search_common(mem_ctx, level, blob, data, &ofs, str_flags);
     666      101720 :                 if (!NT_STATUS_IS_OK(status)) {
     667           0 :                         return -1;
     668             :                 }
     669      101720 :                 return ofs;
     670             :         }
     671             :         }
     672             : 
     673             :         /* invalid level */
     674           0 :         return -1;
     675             : }
     676             : 
     677             : /****************************************************************************
     678             :  Trans2 search backend - process output.
     679             : ****************************************************************************/
     680       12072 : 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         165 :         int i;
     691         165 :         DATA_BLOB blob2;
     692             : 
     693       12072 :         blob2.data = blob->data;
     694       12072 :         blob2.length = blob->length;
     695             : 
     696      248939 :         for (i=0; i < count; i++) {
     697         221 :                 union smb_search_data search_data;
     698         221 :                 unsigned int len;
     699             : 
     700      236867 :                 len = parse_trans2_search(tree, mem_ctx, level, flags, &blob2, &search_data);
     701      236867 :                 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      236867 :                 if (!callback(private_data, &search_data)) {
     708           0 :                         break;
     709             :                 }
     710             : 
     711      236867 :                 if (len == 0) break;
     712             : 
     713      236867 :                 blob2.data += len;
     714      236867 :                 blob2.length -= len;
     715             :         }
     716             : 
     717       12072 :         return NT_STATUS_OK;
     718             : }
     719             : 
     720             : 
     721             : /* Implements trans2findfirst2 and old search
     722             :  */
     723       12932 : _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       12932 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     729         175 :         NTSTATUS status;
     730             : 
     731       12932 :         switch (io->generic.level) {
     732         210 :         case RAW_SEARCH_SEARCH:
     733             :         case RAW_SEARCH_FFIRST:
     734             :         case RAW_SEARCH_FUNIQUE:
     735         210 :                 return smb_raw_search_first_old(tree, mem_ctx, io, private_data, callback);
     736             : 
     737       12547 :         case RAW_SEARCH_TRANS2:
     738       12547 :                 break;
     739             : 
     740           0 :         case RAW_SEARCH_SMB2:
     741           0 :                 return NT_STATUS_INVALID_LEVEL;
     742             :         }
     743             : 
     744       12722 :         status = smb_raw_search_first_blob(tree, mem_ctx,
     745             :                                            io, &p_blob, &d_blob);
     746       12722 :         if (!NT_STATUS_IS_OK(status)) {
     747        2715 :                 return status;
     748             :         }
     749             : 
     750       10007 :         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       10007 :         io->t2ffirst.out.handle = SVAL(p_blob.data, 0);
     758       10007 :         io->t2ffirst.out.count = SVAL(p_blob.data, 2);
     759       10007 :         io->t2ffirst.out.end_of_search = SVAL(p_blob.data, 4);
     760             : 
     761       10007 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     762             :                                           io->generic.data_level,
     763       10007 :                                           io->t2ffirst.in.flags, io->t2ffirst.out.count,
     764             :                                           &d_blob, private_data, callback);
     765             : 
     766       10007 :         return status;
     767             : }
     768             : 
     769             : /* Implements trans2findnext2 and old smbsearch
     770             :  */
     771        2464 : 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        2464 :         DATA_BLOB p_blob = data_blob_null, d_blob = data_blob_null;
     777           0 :         NTSTATUS status;
     778             : 
     779        2464 :         switch (io->generic.level) {
     780         399 :         case RAW_SEARCH_SEARCH:
     781             :         case RAW_SEARCH_FFIRST:
     782         399 :                 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        2065 :         case RAW_SEARCH_TRANS2:
     788        2065 :                 break;
     789             : 
     790           0 :         case RAW_SEARCH_SMB2:
     791           0 :                 return NT_STATUS_INVALID_LEVEL;
     792             :         }
     793             : 
     794        2065 :         status = smb_raw_search_next_blob(tree, mem_ctx,
     795             :                                           io, &p_blob, &d_blob);
     796        2065 :         if (!NT_STATUS_IS_OK(status)) {
     797           0 :                 return status;
     798             :         }
     799             : 
     800        2065 :         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        2065 :         io->t2fnext.out.count = SVAL(p_blob.data, 0);
     808        2065 :         io->t2fnext.out.end_of_search = SVAL(p_blob.data, 2);
     809             : 
     810        2065 :         status = smb_raw_t2search_backend(tree, mem_ctx,
     811             :                                           io->generic.data_level,
     812        2065 :                                           io->t2fnext.in.flags, io->t2fnext.out.count,
     813             :                                           &d_blob, private_data, callback);
     814             : 
     815        2065 :         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           0 :         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.14