root/source4/smb_server/smb/receive.c

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

DEFINITIONS

This source file includes following definitions.
  1. smbsrv_send_oplock_break
  2. smbsrv_recv_smb_request
  3. smb_fn_name
  4. switch_message
  5. smbsrv_chain_reply
  6. smbsrv_init_smb_connection

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    process incoming packets - main loop
   4    Copyright (C) Andrew Tridgell 1992-2005
   5    Copyright (C) James J Myers 2003 <myersjj@samba.org>
   6    Copyright (C) Stefan Metzmacher 2004-2005
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "system/time.h"
  24 #include "smbd/service_stream.h"
  25 #include "smb_server/smb_server.h"
  26 #include "smb_server/service_smb_proto.h"
  27 #include "ntvfs/ntvfs.h"
  28 #include "system/filesys.h"
  29 #include "param/param.h"
  30 
  31 
  32 /*
  33   send an oplock break request to a client
  34 */
  35 NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level)
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon);
  38         struct smbsrv_request *req;
  39 
  40         req = smbsrv_init_request(tcon->smb_conn);
  41         NT_STATUS_HAVE_NO_MEMORY(req);
  42 
  43         smbsrv_setup_reply(req, 8, 0);
  44 
  45         SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
  46         SSVAL(req->out.hdr,HDR_TID,tcon->tid);
  47         SSVAL(req->out.hdr,HDR_PID,0xFFFF);
  48         SSVAL(req->out.hdr,HDR_UID,0);
  49         SSVAL(req->out.hdr,HDR_MID,0xFFFF);
  50         SCVAL(req->out.hdr,HDR_FLG,0);
  51         SSVAL(req->out.hdr,HDR_FLG2,0);
  52 
  53         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
  54         SSVAL(req->out.vwv, VWV(1), 0);
  55         smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs);
  56         SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
  57         SCVAL(req->out.vwv, VWV(3)+1, level);
  58         SIVAL(req->out.vwv, VWV(4), 0);
  59         SSVAL(req->out.vwv, VWV(6), 0);
  60         SSVAL(req->out.vwv, VWV(7), 0);
  61 
  62         smbsrv_send_reply(req);
  63         return NT_STATUS_OK;
  64 }
  65 
  66 static void switch_message(int type, struct smbsrv_request *req);
  67 
  68 /*
  69   These flags determine some of the permissions required to do an operation 
  70 */
  71 #define NEED_SESS               (1<<0)
  72 #define NEED_TCON               (1<<1)
  73 #define SIGNING_NO_REPLY        (1<<2)
  74 /* does VWV(0) of the request hold chaining information */
  75 #define AND_X                   (1<<3)
  76 /* The 64Kb question: are requests > 64K valid? */
  77 #define LARGE_REQUEST   (1<<4)
  78 
  79 /* 
  80    define a list of possible SMB messages and their corresponding
  81    functions. Any message that has a NULL function is unimplemented -
  82    please feel free to contribute implementations!
  83 */
  84 static const struct smb_message_struct
  85 {
  86         const char *name;
  87         void (*fn)(struct smbsrv_request *);
  88 #define message_flags(type) smb_messages[(type) & 0xff].flags
  89         int flags;
  90 }
  91  smb_messages[256] = {
  92 /* 0x00 */ { "SMBmkdir",        smbsrv_reply_mkdir,             NEED_SESS|NEED_TCON },
  93 /* 0x01 */ { "SMBrmdir",        smbsrv_reply_rmdir,             NEED_SESS|NEED_TCON },
  94 /* 0x02 */ { "SMBopen",         smbsrv_reply_open,              NEED_SESS|NEED_TCON },
  95 /* 0x03 */ { "SMBcreate",       smbsrv_reply_mknew,             NEED_SESS|NEED_TCON },
  96 /* 0x04 */ { "SMBclose",        smbsrv_reply_close,             NEED_SESS|NEED_TCON },
  97 /* 0x05 */ { "SMBflush",        smbsrv_reply_flush,             NEED_SESS|NEED_TCON },
  98 /* 0x06 */ { "SMBunlink",       smbsrv_reply_unlink,            NEED_SESS|NEED_TCON },
  99 /* 0x07 */ { "SMBmv",           smbsrv_reply_mv,                NEED_SESS|NEED_TCON },
 100 /* 0x08 */ { "SMBgetatr",       smbsrv_reply_getatr,            NEED_SESS|NEED_TCON },
 101 /* 0x09 */ { "SMBsetatr",       smbsrv_reply_setatr,            NEED_SESS|NEED_TCON },
 102 /* 0x0a */ { "SMBread",         smbsrv_reply_read,              NEED_SESS|NEED_TCON },
 103 /* 0x0b */ { "SMBwrite",        smbsrv_reply_write,             NEED_SESS|NEED_TCON },
 104 /* 0x0c */ { "SMBlock",         smbsrv_reply_lock,              NEED_SESS|NEED_TCON },
 105 /* 0x0d */ { "SMBunlock",       smbsrv_reply_unlock,            NEED_SESS|NEED_TCON },
 106 /* 0x0e */ { "SMBctemp",        smbsrv_reply_ctemp,             NEED_SESS|NEED_TCON },
 107 /* 0x0f */ { "SMBmknew",        smbsrv_reply_mknew,             NEED_SESS|NEED_TCON }, 
 108 /* 0x10 */ { "SMBchkpth",       smbsrv_reply_chkpth,            NEED_SESS|NEED_TCON },
 109 /* 0x11 */ { "SMBexit",         smbsrv_reply_exit,              NEED_SESS },
 110 /* 0x12 */ { "SMBlseek",        smbsrv_reply_lseek,             NEED_SESS|NEED_TCON },
 111 /* 0x13 */ { "SMBlockread",     smbsrv_reply_lockread,          NEED_SESS|NEED_TCON },
 112 /* 0x14 */ { "SMBwriteunlock",  smbsrv_reply_writeunlock,       NEED_SESS|NEED_TCON },
 113 /* 0x15 */ { NULL, NULL, 0 },
 114 /* 0x16 */ { NULL, NULL, 0 },
 115 /* 0x17 */ { NULL, NULL, 0 },
 116 /* 0x18 */ { NULL, NULL, 0 },
 117 /* 0x19 */ { NULL, NULL, 0 },
 118 /* 0x1a */ { "SMBreadbraw",     smbsrv_reply_readbraw,          NEED_SESS|NEED_TCON },
 119 /* 0x1b */ { "SMBreadBmpx",     smbsrv_reply_readbmpx,          NEED_SESS|NEED_TCON },
 120 /* 0x1c */ { "SMBreadBs",       NULL,                           0 },
 121 /* 0x1d */ { "SMBwritebraw",    smbsrv_reply_writebraw,         NEED_SESS|NEED_TCON },
 122 /* 0x1e */ { "SMBwriteBmpx",    smbsrv_reply_writebmpx,         NEED_SESS|NEED_TCON },
 123 /* 0x1f */ { "SMBwriteBs",      smbsrv_reply_writebs,           NEED_SESS|NEED_TCON },
 124 /* 0x20 */ { "SMBwritec",       NULL,                           0 },
 125 /* 0x21 */ { NULL, NULL, 0 },
 126 /* 0x22 */ { "SMBsetattrE",     smbsrv_reply_setattrE,          NEED_SESS|NEED_TCON },
 127 /* 0x23 */ { "SMBgetattrE",     smbsrv_reply_getattrE,          NEED_SESS|NEED_TCON },
 128 /* 0x24 */ { "SMBlockingX",     smbsrv_reply_lockingX,          NEED_SESS|NEED_TCON|AND_X },
 129 /* 0x25 */ { "SMBtrans",        smbsrv_reply_trans,             NEED_SESS|NEED_TCON },
 130 /* 0x26 */ { "SMBtranss",       smbsrv_reply_transs,            NEED_SESS|NEED_TCON },
 131 /* 0x27 */ { "SMBioctl",        smbsrv_reply_ioctl,             NEED_SESS|NEED_TCON },
 132 /* 0x28 */ { "SMBioctls",       NULL,                           NEED_SESS|NEED_TCON },
 133 /* 0x29 */ { "SMBcopy",         smbsrv_reply_copy,              NEED_SESS|NEED_TCON },
 134 /* 0x2a */ { "SMBmove",         NULL,                           NEED_SESS|NEED_TCON },
 135 /* 0x2b */ { "SMBecho",         smbsrv_reply_echo,              0 },
 136 /* 0x2c */ { "SMBwriteclose",   smbsrv_reply_writeclose,        NEED_SESS|NEED_TCON },
 137 /* 0x2d */ { "SMBopenX",        smbsrv_reply_open_and_X,        NEED_SESS|NEED_TCON|AND_X },
 138 /* 0x2e */ { "SMBreadX",        smbsrv_reply_read_and_X,        NEED_SESS|NEED_TCON|AND_X },
 139 /* 0x2f */ { "SMBwriteX",       smbsrv_reply_write_and_X,       NEED_SESS|NEED_TCON|AND_X|LARGE_REQUEST},
 140 /* 0x30 */ { NULL, NULL, 0 },
 141 /* 0x31 */ { NULL, NULL, 0 },
 142 /* 0x32 */ { "SMBtrans2",       smbsrv_reply_trans2,            NEED_SESS|NEED_TCON },
 143 /* 0x33 */ { "SMBtranss2",      smbsrv_reply_transs2,           NEED_SESS|NEED_TCON },
 144 /* 0x34 */ { "SMBfindclose",    smbsrv_reply_findclose,         NEED_SESS|NEED_TCON },
 145 /* 0x35 */ { "SMBfindnclose",   smbsrv_reply_findnclose,        NEED_SESS|NEED_TCON },
 146 /* 0x36 */ { NULL, NULL, 0 },
 147 /* 0x37 */ { NULL, NULL, 0 },
 148 /* 0x38 */ { NULL, NULL, 0 },
 149 /* 0x39 */ { NULL, NULL, 0 },
 150 /* 0x3a */ { NULL, NULL, 0 },
 151 /* 0x3b */ { NULL, NULL, 0 },
 152 /* 0x3c */ { NULL, NULL, 0 },
 153 /* 0x3d */ { NULL, NULL, 0 },
 154 /* 0x3e */ { NULL, NULL, 0 },
 155 /* 0x3f */ { NULL, NULL, 0 },
 156 /* 0x40 */ { NULL, NULL, 0 },
 157 /* 0x41 */ { NULL, NULL, 0 },
 158 /* 0x42 */ { NULL, NULL, 0 },
 159 /* 0x43 */ { NULL, NULL, 0 },
 160 /* 0x44 */ { NULL, NULL, 0 },
 161 /* 0x45 */ { NULL, NULL, 0 },
 162 /* 0x46 */ { NULL, NULL, 0 },
 163 /* 0x47 */ { NULL, NULL, 0 },
 164 /* 0x48 */ { NULL, NULL, 0 },
 165 /* 0x49 */ { NULL, NULL, 0 },
 166 /* 0x4a */ { NULL, NULL, 0 },
 167 /* 0x4b */ { NULL, NULL, 0 },
 168 /* 0x4c */ { NULL, NULL, 0 },
 169 /* 0x4d */ { NULL, NULL, 0 },
 170 /* 0x4e */ { NULL, NULL, 0 },
 171 /* 0x4f */ { NULL, NULL, 0 },
 172 /* 0x50 */ { NULL, NULL, 0 },
 173 /* 0x51 */ { NULL, NULL, 0 },
 174 /* 0x52 */ { NULL, NULL, 0 },
 175 /* 0x53 */ { NULL, NULL, 0 },
 176 /* 0x54 */ { NULL, NULL, 0 },
 177 /* 0x55 */ { NULL, NULL, 0 },
 178 /* 0x56 */ { NULL, NULL, 0 },
 179 /* 0x57 */ { NULL, NULL, 0 },
 180 /* 0x58 */ { NULL, NULL, 0 },
 181 /* 0x59 */ { NULL, NULL, 0 },
 182 /* 0x5a */ { NULL, NULL, 0 },
 183 /* 0x5b */ { NULL, NULL, 0 },
 184 /* 0x5c */ { NULL, NULL, 0 },
 185 /* 0x5d */ { NULL, NULL, 0 },
 186 /* 0x5e */ { NULL, NULL, 0 },
 187 /* 0x5f */ { NULL, NULL, 0 },
 188 /* 0x60 */ { NULL, NULL, 0 },
 189 /* 0x61 */ { NULL, NULL, 0 },
 190 /* 0x62 */ { NULL, NULL, 0 },
 191 /* 0x63 */ { NULL, NULL, 0 },
 192 /* 0x64 */ { NULL, NULL, 0 },
 193 /* 0x65 */ { NULL, NULL, 0 },
 194 /* 0x66 */ { NULL, NULL, 0 },
 195 /* 0x67 */ { NULL, NULL, 0 },
 196 /* 0x68 */ { NULL, NULL, 0 },
 197 /* 0x69 */ { NULL, NULL, 0 },
 198 /* 0x6a */ { NULL, NULL, 0 },
 199 /* 0x6b */ { NULL, NULL, 0 },
 200 /* 0x6c */ { NULL, NULL, 0 },
 201 /* 0x6d */ { NULL, NULL, 0 },
 202 /* 0x6e */ { NULL, NULL, 0 },
 203 /* 0x6f */ { NULL, NULL, 0 },
 204 /* 0x70 */ { "SMBtcon",         smbsrv_reply_tcon,              NEED_SESS },
 205 /* 0x71 */ { "SMBtdis",         smbsrv_reply_tdis,              NEED_TCON },
 206 /* 0x72 */ { "SMBnegprot",      smbsrv_reply_negprot,           0 },
 207 /* 0x73 */ { "SMBsesssetupX",   smbsrv_reply_sesssetup,         AND_X },
 208 /* 0x74 */ { "SMBulogoffX",     smbsrv_reply_ulogoffX,          NEED_SESS|AND_X }, /* ulogoff doesn't give a valid TID */
 209 /* 0x75 */ { "SMBtconX",        smbsrv_reply_tcon_and_X,        NEED_SESS|AND_X },
 210 /* 0x76 */ { NULL, NULL, 0 },
 211 /* 0x77 */ { NULL, NULL, 0 },
 212 /* 0x78 */ { NULL, NULL, 0 },
 213 /* 0x79 */ { NULL, NULL, 0 },
 214 /* 0x7a */ { NULL, NULL, 0 },
 215 /* 0x7b */ { NULL, NULL, 0 },
 216 /* 0x7c */ { NULL, NULL, 0 },
 217 /* 0x7d */ { NULL, NULL, 0 },
 218 /* 0x7e */ { NULL, NULL, 0 },
 219 /* 0x7f */ { NULL, NULL, 0 },
 220 /* 0x80 */ { "SMBdskattr",      smbsrv_reply_dskattr,           NEED_SESS|NEED_TCON },
 221 /* 0x81 */ { "SMBsearch",       smbsrv_reply_search,            NEED_SESS|NEED_TCON },
 222 /* 0x82 */ { "SMBffirst",       smbsrv_reply_search,            NEED_SESS|NEED_TCON },
 223 /* 0x83 */ { "SMBfunique",      smbsrv_reply_search,            NEED_SESS|NEED_TCON },
 224 /* 0x84 */ { "SMBfclose",       smbsrv_reply_fclose,            NEED_SESS|NEED_TCON },
 225 /* 0x85 */ { NULL, NULL, 0 },
 226 /* 0x86 */ { NULL, NULL, 0 },
 227 /* 0x87 */ { NULL, NULL, 0 },
 228 /* 0x88 */ { NULL, NULL, 0 },
 229 /* 0x89 */ { NULL, NULL, 0 },
 230 /* 0x8a */ { NULL, NULL, 0 },
 231 /* 0x8b */ { NULL, NULL, 0 },
 232 /* 0x8c */ { NULL, NULL, 0 },
 233 /* 0x8d */ { NULL, NULL, 0 },
 234 /* 0x8e */ { NULL, NULL, 0 },
 235 /* 0x8f */ { NULL, NULL, 0 },
 236 /* 0x90 */ { NULL, NULL, 0 },
 237 /* 0x91 */ { NULL, NULL, 0 },
 238 /* 0x92 */ { NULL, NULL, 0 },
 239 /* 0x93 */ { NULL, NULL, 0 },
 240 /* 0x94 */ { NULL, NULL, 0 },
 241 /* 0x95 */ { NULL, NULL, 0 },
 242 /* 0x96 */ { NULL, NULL, 0 },
 243 /* 0x97 */ { NULL, NULL, 0 },
 244 /* 0x98 */ { NULL, NULL, 0 },
 245 /* 0x99 */ { NULL, NULL, 0 },
 246 /* 0x9a */ { NULL, NULL, 0 },
 247 /* 0x9b */ { NULL, NULL, 0 },
 248 /* 0x9c */ { NULL, NULL, 0 },
 249 /* 0x9d */ { NULL, NULL, 0 },
 250 /* 0x9e */ { NULL, NULL, 0 },
 251 /* 0x9f */ { NULL, NULL, 0 },
 252 /* 0xa0 */ { "SMBnttrans",      smbsrv_reply_nttrans,           NEED_SESS|NEED_TCON|LARGE_REQUEST },
 253 /* 0xa1 */ { "SMBnttranss",     smbsrv_reply_nttranss,          NEED_SESS|NEED_TCON },
 254 /* 0xa2 */ { "SMBntcreateX",    smbsrv_reply_ntcreate_and_X,    NEED_SESS|NEED_TCON|AND_X },
 255 /* 0xa3 */ { NULL, NULL, 0 },
 256 /* 0xa4 */ { "SMBntcancel",     smbsrv_reply_ntcancel,          NEED_SESS|NEED_TCON|SIGNING_NO_REPLY },
 257 /* 0xa5 */ { "SMBntrename",     smbsrv_reply_ntrename,          NEED_SESS|NEED_TCON },
 258 /* 0xa6 */ { NULL, NULL, 0 },
 259 /* 0xa7 */ { NULL, NULL, 0 },
 260 /* 0xa8 */ { NULL, NULL, 0 },
 261 /* 0xa9 */ { NULL, NULL, 0 },
 262 /* 0xaa */ { NULL, NULL, 0 },
 263 /* 0xab */ { NULL, NULL, 0 },
 264 /* 0xac */ { NULL, NULL, 0 },
 265 /* 0xad */ { NULL, NULL, 0 },
 266 /* 0xae */ { NULL, NULL, 0 },
 267 /* 0xaf */ { NULL, NULL, 0 },
 268 /* 0xb0 */ { NULL, NULL, 0 },
 269 /* 0xb1 */ { NULL, NULL, 0 },
 270 /* 0xb2 */ { NULL, NULL, 0 },
 271 /* 0xb3 */ { NULL, NULL, 0 },
 272 /* 0xb4 */ { NULL, NULL, 0 },
 273 /* 0xb5 */ { NULL, NULL, 0 },
 274 /* 0xb6 */ { NULL, NULL, 0 },
 275 /* 0xb7 */ { NULL, NULL, 0 },
 276 /* 0xb8 */ { NULL, NULL, 0 },
 277 /* 0xb9 */ { NULL, NULL, 0 },
 278 /* 0xba */ { NULL, NULL, 0 },
 279 /* 0xbb */ { NULL, NULL, 0 },
 280 /* 0xbc */ { NULL, NULL, 0 },
 281 /* 0xbd */ { NULL, NULL, 0 },
 282 /* 0xbe */ { NULL, NULL, 0 },
 283 /* 0xbf */ { NULL, NULL, 0 },
 284 /* 0xc0 */ { "SMBsplopen",      smbsrv_reply_printopen,         NEED_SESS|NEED_TCON },
 285 /* 0xc1 */ { "SMBsplwr",        smbsrv_reply_printwrite,        NEED_SESS|NEED_TCON },
 286 /* 0xc2 */ { "SMBsplclose",     smbsrv_reply_printclose,        NEED_SESS|NEED_TCON },
 287 /* 0xc3 */ { "SMBsplretq",      smbsrv_reply_printqueue,        NEED_SESS|NEED_TCON },
 288 /* 0xc4 */ { NULL, NULL, 0 },
 289 /* 0xc5 */ { NULL, NULL, 0 },
 290 /* 0xc6 */ { NULL, NULL, 0 },
 291 /* 0xc7 */ { NULL, NULL, 0 },
 292 /* 0xc8 */ { NULL, NULL, 0 },
 293 /* 0xc9 */ { NULL, NULL, 0 },
 294 /* 0xca */ { NULL, NULL, 0 },
 295 /* 0xcb */ { NULL, NULL, 0 },
 296 /* 0xcc */ { NULL, NULL, 0 },
 297 /* 0xcd */ { NULL, NULL, 0 },
 298 /* 0xce */ { NULL, NULL, 0 },
 299 /* 0xcf */ { NULL, NULL, 0 },
 300 /* 0xd0 */ { "SMBsends",        NULL,                           0 },
 301 /* 0xd1 */ { "SMBsendb",        NULL,                           0 },
 302 /* 0xd2 */ { "SMBfwdname",      NULL,                           0 },
 303 /* 0xd3 */ { "SMBcancelf",      NULL,                           0 },
 304 /* 0xd4 */ { "SMBgetmac",       NULL,                           0 },
 305 /* 0xd5 */ { "SMBsendstrt",     NULL,                           0 },
 306 /* 0xd6 */ { "SMBsendend",      NULL,                           0 },
 307 /* 0xd7 */ { "SMBsendtxt",      NULL,                           0 },
 308 /* 0xd8 */ { NULL, NULL, 0 },
 309 /* 0xd9 */ { NULL, NULL, 0 },
 310 /* 0xda */ { NULL, NULL, 0 },
 311 /* 0xdb */ { NULL, NULL, 0 },
 312 /* 0xdc */ { NULL, NULL, 0 },
 313 /* 0xdd */ { NULL, NULL, 0 },
 314 /* 0xde */ { NULL, NULL, 0 },
 315 /* 0xdf */ { NULL, NULL, 0 },
 316 /* 0xe0 */ { NULL, NULL, 0 },
 317 /* 0xe1 */ { NULL, NULL, 0 },
 318 /* 0xe2 */ { NULL, NULL, 0 },
 319 /* 0xe3 */ { NULL, NULL, 0 },
 320 /* 0xe4 */ { NULL, NULL, 0 },
 321 /* 0xe5 */ { NULL, NULL, 0 },
 322 /* 0xe6 */ { NULL, NULL, 0 },
 323 /* 0xe7 */ { NULL, NULL, 0 },
 324 /* 0xe8 */ { NULL, NULL, 0 },
 325 /* 0xe9 */ { NULL, NULL, 0 },
 326 /* 0xea */ { NULL, NULL, 0 },
 327 /* 0xeb */ { NULL, NULL, 0 },
 328 /* 0xec */ { NULL, NULL, 0 },
 329 /* 0xed */ { NULL, NULL, 0 },
 330 /* 0xee */ { NULL, NULL, 0 },
 331 /* 0xef */ { NULL, NULL, 0 },
 332 /* 0xf0 */ { NULL, NULL, 0 },
 333 /* 0xf1 */ { NULL, NULL, 0 },
 334 /* 0xf2 */ { NULL, NULL, 0 },
 335 /* 0xf3 */ { NULL, NULL, 0 },
 336 /* 0xf4 */ { NULL, NULL, 0 },
 337 /* 0xf5 */ { NULL, NULL, 0 },
 338 /* 0xf6 */ { NULL, NULL, 0 },
 339 /* 0xf7 */ { NULL, NULL, 0 },
 340 /* 0xf8 */ { NULL, NULL, 0 },
 341 /* 0xf9 */ { NULL, NULL, 0 },
 342 /* 0xfa */ { NULL, NULL, 0 },
 343 /* 0xfb */ { NULL, NULL, 0 },
 344 /* 0xfc */ { NULL, NULL, 0 },
 345 /* 0xfd */ { NULL, NULL, 0 },
 346 /* 0xfe */ { NULL, NULL, 0 },
 347 /* 0xff */ { NULL, NULL, 0 }
 348 };
 349 
 350 /****************************************************************************
 351 receive a SMB request header from the wire, forming a request_context
 352 from the result
 353 ****************************************************************************/
 354 NTSTATUS smbsrv_recv_smb_request(void *private_data, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
 355 {
 356         struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
 357         struct smbsrv_request *req;
 358         struct timeval cur_time = timeval_current();
 359         uint8_t command;
 360 
 361         smb_conn->statistics.last_request_time = cur_time;
 362 
 363         /* see if its a special NBT packet */
 364         if (CVAL(blob.data, 0) != 0) {
 365                 req = smbsrv_init_request(smb_conn);
 366                 NT_STATUS_HAVE_NO_MEMORY(req);
 367 
 368                 ZERO_STRUCT(req->in);
 369 
 370                 req->in.buffer = talloc_steal(req, blob.data);
 371                 req->in.size = blob.length;
 372                 req->request_time = cur_time;
 373 
 374                 smbsrv_reply_special(req);
 375                 return NT_STATUS_OK;
 376         }
 377 
 378         if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) {
 379                 DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length));
 380                 smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
 381                 return NT_STATUS_OK;
 382         }
 383 
 384         /* Make sure this is an SMB packet */
 385         if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) {
 386                 DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n",
 387                          (long)blob.length));
 388                 smbsrv_terminate_connection(smb_conn, "Non-SMB packet");
 389                 return NT_STATUS_OK;
 390         }
 391 
 392         req = smbsrv_init_request(smb_conn);
 393         NT_STATUS_HAVE_NO_MEMORY(req);
 394 
 395         req->in.buffer = talloc_steal(req, blob.data);
 396         req->in.size = blob.length;
 397         req->request_time = cur_time;
 398         req->chained_fnum = -1;
 399         req->in.allocated = req->in.size;
 400         req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
 401         req->in.vwv = req->in.hdr + HDR_VWV;
 402         req->in.wct = CVAL(req->in.hdr, HDR_WCT);
 403 
 404         command = CVAL(req->in.hdr, HDR_COM);
 405 
 406         if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) {
 407                 req->in.data = req->in.vwv + VWV(req->in.wct) + 2;
 408                 req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
 409 
 410                 /* the bcc length is only 16 bits, but some packets
 411                    (such as SMBwriteX) can be much larger than 64k. We
 412                    detect this by looking for a large non-chained NBT
 413                    packet (at least 64k bigger than what is
 414                    specified). If it is detected then the NBT size is
 415                    used instead of the bcc size */
 416                 if (req->in.data_size + 0x10000 <= 
 417                     req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
 418                         ( message_flags(command) & LARGE_REQUEST) &&
 419                         ( !(message_flags(command) & AND_X) ||
 420                       (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) )
 421                         ) {
 422                         /* its an oversized packet! fun for all the family */
 423                         req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
 424                 }
 425         }
 426 
 427         if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) {
 428                 DEBUG(2,("Invalid SMB word count %d\n", req->in.wct));
 429                 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
 430                 return NT_STATUS_OK;
 431         }
 432  
 433         if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) {
 434                 DEBUG(2,("Invalid SMB buffer length count %d\n", 
 435                          (int)req->in.data_size));
 436                 smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet");
 437                 return NT_STATUS_OK;
 438         }
 439 
 440         req->flags2     = SVAL(req->in.hdr, HDR_FLG2);
 441 
 442         /* fix the bufinfo */
 443         smbsrv_setup_bufinfo(req);
 444 
 445         if (!smbsrv_signing_check_incoming(req)) {
 446                 smbsrv_send_error(req, NT_STATUS_ACCESS_DENIED);
 447                 return NT_STATUS_OK;
 448         }
 449 
 450         command = CVAL(req->in.hdr, HDR_COM);
 451         switch_message(command, req);
 452         return NT_STATUS_OK;
 453 }
 454 
 455 /****************************************************************************
 456 return a string containing the function name of a SMB command
 457 ****************************************************************************/
 458 static const char *smb_fn_name(uint8_t type)
     /* [<][>][^][v][top][bottom][index][help] */
 459 {
 460         const char *unknown_name = "SMBunknown";
 461 
 462         if (smb_messages[type].name == NULL)
 463                 return unknown_name;
 464 
 465         return smb_messages[type].name;
 466 }
 467 
 468 
 469 /****************************************************************************
 470  Do a switch on the message type and call the specific reply function for this 
 471 message. Unlike earlier versions of Samba the reply functions are responsible
 472 for sending the reply themselves, rather than returning a size to this function
 473 The reply functions may also choose to delay the processing by pushing the message
 474 onto the message queue
 475 ****************************************************************************/
 476 static void switch_message(int type, struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 477 {
 478         int flags;
 479         struct smbsrv_connection *smb_conn = req->smb_conn;
 480         NTSTATUS status;
 481 
 482         type &= 0xff;
 483 
 484         errno = 0;
 485 
 486         if (smb_messages[type].fn == NULL) {
 487                 DEBUG(0,("Unknown message type %d!\n",type));
 488                 smbsrv_reply_unknown(req);
 489                 return;
 490         }
 491 
 492         flags = smb_messages[type].flags;
 493 
 494         req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID), req->request_time);
 495 
 496         if (!req->session) {
 497                 /* setup the user context for this request if it
 498                    hasn't already been initialised (to cope with SMB
 499                    chaining) */
 500 
 501                 /* In share mode security we must ignore the vuid. */
 502                 if (smb_conn->config.security == SEC_SHARE) {
 503                         if (req->tcon) {
 504                                 req->session = req->tcon->sec_share.session;
 505                         }
 506                 } else {
 507                         req->session = smbsrv_session_find(req->smb_conn, SVAL(req->in.hdr,HDR_UID), req->request_time);
 508                 }
 509         }
 510 
 511         DEBUG(5,("switch message %s (task_id %u)\n",
 512                  smb_fn_name(type), (unsigned)req->smb_conn->connection->server_id.id));
 513 
 514         /* this must be called before we do any reply */
 515         if (flags & SIGNING_NO_REPLY) {
 516                 smbsrv_signing_no_reply(req);
 517         }
 518 
 519         /* see if the vuid is valid */
 520         if ((flags & NEED_SESS) && !req->session) {
 521                 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
 522                 /* amazingly, the error code depends on the command */
 523                 switch (type) {
 524                 case SMBntcreateX:
 525                 case SMBntcancel:
 526                 case SMBulogoffX:
 527                         break;
 528                 default:
 529                         if (req->smb_conn->config.nt_status_support &&
 530                             req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
 531                                 status = NT_STATUS_INVALID_HANDLE;
 532                         }
 533                         break;
 534                 }
 535                 /* 
 536                  * TODO:
 537                  * don't know how to handle smb signing for this case 
 538                  * so just skip the reply
 539                  */
 540                 if ((flags & SIGNING_NO_REPLY) &&
 541                     (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
 542                         DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
 543                                 smb_fn_name(type), nt_errstr(status)));
 544                         talloc_free(req);
 545                         return;
 546                 }
 547                 smbsrv_send_error(req, status);
 548                 return;
 549         }
 550 
 551         /* does this protocol need a valid tree connection? */
 552         if ((flags & NEED_TCON) && !req->tcon) {
 553                 status = NT_STATUS_DOS(ERRSRV, ERRinvnid);
 554                 /* amazingly, the error code depends on the command */
 555                 switch (type) {
 556                 case SMBntcreateX:
 557                 case SMBntcancel:
 558                 case SMBtdis:
 559                         break;
 560                 default:
 561                         if (req->smb_conn->config.nt_status_support &&
 562                             req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
 563                                 status = NT_STATUS_INVALID_HANDLE;
 564                         }
 565                         break;
 566                 }
 567                 /* 
 568                  * TODO:
 569                  * don't know how to handle smb signing for this case 
 570                  * so just skip the reply
 571                  */
 572                 if ((flags & SIGNING_NO_REPLY) &&
 573                     (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) {
 574                         DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n",
 575                                 smb_fn_name(type), nt_errstr(status)));
 576                         talloc_free(req);
 577                         return;
 578                 }
 579                 smbsrv_send_error(req, status);
 580                 return;
 581         }
 582 
 583         smb_messages[type].fn(req);
 584 }
 585 
 586 /*
 587   we call this when first first part of a possibly chained request has been completed
 588   and we need to call the 2nd part, if any
 589 */
 590 void smbsrv_chain_reply(struct smbsrv_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 591 {
 592         uint16_t chain_cmd, chain_offset;
 593         uint8_t *vwv, *data;
 594         uint16_t wct;
 595         uint16_t data_size;
 596 
 597         if (req->in.wct < 2 || req->out.wct < 2) {
 598                 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
 599                 return;
 600         }
 601 
 602         chain_cmd    = CVAL(req->in.vwv, VWV(0));
 603         chain_offset = SVAL(req->in.vwv, VWV(1));
 604 
 605         if (chain_cmd == SMB_CHAIN_NONE) {
 606                 /* end of chain */
 607                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
 608                 SSVAL(req->out.vwv, VWV(1), 0);
 609                 smbsrv_send_reply(req);
 610                 return;
 611         }
 612 
 613         if (chain_offset + req->in.hdr >= req->in.buffer + req->in.size) {
 614                 goto error;
 615         }
 616 
 617         wct = CVAL(req->in.hdr, chain_offset);
 618         vwv = req->in.hdr + chain_offset + 1;
 619 
 620         if (vwv + VWV(wct) + 2 > req->in.buffer + req->in.size) {
 621                 goto error;
 622         }
 623 
 624         data_size = SVAL(vwv, VWV(wct));
 625         data = vwv + VWV(wct) + 2;
 626 
 627         if (data + data_size > req->in.buffer + req->in.size) {
 628                 goto error;
 629         }
 630 
 631         /* all seems legit */
 632         req->in.vwv = vwv;
 633         req->in.wct = wct;
 634         req->in.data = data;
 635         req->in.data_size = data_size;
 636         req->in.ptr = data;
 637 
 638         /* fix the bufinfo */
 639         smbsrv_setup_bufinfo(req);
 640 
 641         req->chain_count++;
 642 
 643         SSVAL(req->out.vwv, VWV(0), chain_cmd);
 644         SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
 645 
 646         /* cleanup somestuff for the next request */
 647         talloc_free(req->ntvfs);
 648         req->ntvfs = NULL;
 649         talloc_free(req->io_ptr);
 650         req->io_ptr = NULL;
 651 
 652         switch_message(chain_cmd, req);
 653         return;
 654 
 655 error:
 656         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
 657         SSVAL(req->out.vwv, VWV(1), 0);
 658         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
 659 }
 660 
 661 /*
 662  * init the SMB protocol related stuff
 663  */
 664 NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn, struct loadparm_context *lp_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 665 {
 666         NTSTATUS status;
 667 
 668         /* now initialise a few default values associated with this smb socket */
 669         smb_conn->negotiate.max_send = 0xFFFF;
 670 
 671         /* this is the size that w2k uses, and it appears to be important for
 672            good performance */
 673         smb_conn->negotiate.max_recv = lp_max_xmit(lp_ctx);
 674 
 675         smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
 676 
 677         smb_conn->config.security = lp_security(lp_ctx);
 678         smb_conn->config.nt_status_support = lp_nt_status_support(lp_ctx);
 679 
 680         status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
 681         NT_STATUS_NOT_OK_RETURN(status);
 682 
 683         status = smbsrv_smb_init_tcons(smb_conn);
 684         NT_STATUS_NOT_OK_RETURN(status);
 685 
 686         smbsrv_init_signing(smb_conn);
 687 
 688         return NT_STATUS_OK;
 689 }

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