root/source4/smb_server/smb/search.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_fill_info
  2. find_callback
  3. reply_search_first_send
  4. reply_search_next_send
  5. smbsrv_reply_search
  6. reply_fclose_send
  7. smbsrv_reply_fclose

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

/* [<][>][^][v][top][bottom][index][help] */