~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/smb_server/smb/receive.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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
}