r3206: - added the reverse map for ERRbaduid to NT_STATUS_INVALID_HANDLE
[kai/samba.git] / source4 / torture / raw / context.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for session setup operations
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #define BASEDIR "\\rawcontext"
24
25 #define CHECK_STATUS(status, correct) do { \
26         if (!NT_STATUS_EQUAL(status, correct)) { \
27                 printf("(%s) Incorrect status %s - should be %s\n", \
28                        __location__, nt_errstr(status), nt_errstr(correct)); \
29                 ret = False; \
30                 goto done; \
31         }} while (0)
32
33 #define CHECK_VALUE(v, correct) do { \
34         if ((v) != (correct)) { \
35                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
36                        __location__, #v, v, correct); \
37                 ret = False; \
38                 goto done; \
39         }} while (0)
40
41 #define CHECK_NOT_VALUE(v, correct) do { \
42         if ((v) == (correct)) { \
43                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
44                        __location__, #v, v, correct); \
45                 ret = False; \
46                 goto done; \
47         }} while (0)
48
49
50 /*
51   test session ops
52 */
53 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
54 {
55         NTSTATUS status;
56         BOOL ret = True;
57         const char *username, *domain, *password;
58         struct smbcli_session *session;
59         struct smbcli_session *session2;
60         struct smbcli_session *session3;
61         struct smbcli_tree *tree;
62         union smb_sesssetup setup;
63         union smb_open io;
64         union smb_write wr;
65         union smb_close cl;
66         int fnum;
67         const char *fname = BASEDIR "\\test.txt";
68         char c = 1;
69
70         printf("TESTING SESSION HANDLING\n");
71
72         if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
73             NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
74                 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
75                 return False;
76         }
77
78         username = lp_parm_string(-1, "torture", "username");
79         password = lp_parm_string(-1, "torture", "password");
80         domain = lp_parm_string(-1, "torture", "userdomain");
81
82         printf("create a second security context on the same transport\n");
83         session = smbcli_session_init(cli->transport);
84
85         setup.generic.level = RAW_SESSSETUP_GENERIC;
86         setup.generic.in.sesskey = cli->transport->negotiate.sesskey;
87         setup.generic.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
88         setup.generic.in.password = password;
89         setup.generic.in.user = username;
90         setup.generic.in.domain = domain;
91
92         status = smb_raw_session_setup(session, mem_ctx, &setup);
93         CHECK_STATUS(status, NT_STATUS_OK);
94
95         session->vuid = setup.generic.out.vuid;
96
97         printf("create a third security context on the same transport, with vuid set\n");
98         session2 = smbcli_session_init(cli->transport);
99
100         session2->vuid = session->vuid;
101         setup.generic.level = RAW_SESSSETUP_GENERIC;
102         setup.generic.in.sesskey = cli->transport->negotiate.sesskey;
103         setup.generic.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
104         setup.generic.in.password = password;
105         setup.generic.in.user = username;
106         setup.generic.in.domain = domain;
107
108         status = smb_raw_session_setup(session2, mem_ctx, &setup);
109         CHECK_STATUS(status, NT_STATUS_OK);
110
111         session2->vuid = setup.generic.out.vuid;
112         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
113         
114         CHECK_NOT_VALUE(session->vuid, session2->vuid);
115         talloc_free(session2);
116
117         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
118                 printf("create a fourth security context on the same transport, without extended security\n");
119                 session3 = smbcli_session_init(cli->transport);
120
121                 session3->vuid = session->vuid;
122                 setup.generic.level = RAW_SESSSETUP_GENERIC;
123                 setup.generic.in.sesskey = cli->transport->negotiate.sesskey;
124                 setup.generic.in.capabilities = 0; /* force a non extended security login (should fail) */
125                 setup.generic.in.password = password;
126                 setup.generic.in.user = username;
127                 setup.generic.in.domain = domain;
128
129                 status = smb_raw_session_setup(session3, mem_ctx, &setup);
130                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
131
132                 talloc_free(session3);
133         }
134                 
135         printf("use the same tree as the existing connection\n");
136         tree = smbcli_tree_init(session);
137         tree->tid = cli->tree->tid;
138
139         printf("create a file using the new vuid\n");
140         io.generic.level = RAW_OPEN_NTCREATEX;
141         io.ntcreatex.in.root_fid = 0;
142         io.ntcreatex.in.flags = 0;
143         io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
144         io.ntcreatex.in.create_options = 0;
145         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
146         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
147         io.ntcreatex.in.alloc_size = 0;
148         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
149         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
150         io.ntcreatex.in.security_flags = 0;
151         io.ntcreatex.in.fname = fname;
152         status = smb_raw_open(tree, mem_ctx, &io);
153         CHECK_STATUS(status, NT_STATUS_OK);
154         fnum = io.ntcreatex.out.fnum;
155
156         printf("write using the old vuid\n");
157         wr.generic.level = RAW_WRITE_WRITEX;
158         wr.writex.in.fnum = fnum;
159         wr.writex.in.offset = 0;
160         wr.writex.in.wmode = 0;
161         wr.writex.in.remaining = 0;
162         wr.writex.in.count = 1;
163         wr.writex.in.data = &c;
164
165         status = smb_raw_write(cli->tree, &wr);
166         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
167
168         printf("write with the new vuid\n");
169         status = smb_raw_write(tree, &wr);
170         CHECK_STATUS(status, NT_STATUS_OK);
171         CHECK_VALUE(wr.writex.out.nwritten, 1);
172
173         printf("logoff the new vuid\n");
174         status = smb_raw_ulogoff(session);
175         CHECK_STATUS(status, NT_STATUS_OK);
176         talloc_free(session);
177
178         printf("the new vuid should not now be accessible\n");
179         status = smb_raw_write(tree, &wr);
180         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
181
182         printf("the fnum should have been auto-closed\n");
183         cl.close.level = RAW_CLOSE_CLOSE;
184         cl.close.in.fnum = fnum;
185         cl.close.in.write_time = 0;
186         status = smb_raw_close(cli->tree, &cl);
187         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
188
189         talloc_free(tree);
190         
191 done:
192         return ret;
193 }
194
195
196 /*
197   test tree ops
198 */
199 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
200 {
201         NTSTATUS status;
202         BOOL ret = True;
203         const char *share;
204         struct smbcli_tree *tree;
205         union smb_tcon tcon;
206         union smb_open io;
207         union smb_write wr;
208         union smb_close cl;
209         int fnum;
210         const char *fname = BASEDIR "\\test.txt";
211         char c = 1;
212
213         printf("TESTING TREE HANDLING\n");
214
215         if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
216             NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
217                 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
218                 return False;
219         }
220
221         share = lp_parm_string(-1, "torture", "share");
222         
223         printf("create a second tree context on the same session\n");
224         tree = smbcli_tree_init(cli->session);
225
226         tcon.generic.level = RAW_TCON_TCONX;
227         tcon.tconx.in.flags = 0;
228         tcon.tconx.in.password = data_blob(NULL, 0);
229         tcon.tconx.in.path = share;
230         tcon.tconx.in.device = "A:";    
231         status = smb_tree_connect(tree, mem_ctx, &tcon);
232         CHECK_STATUS(status, NT_STATUS_OK);
233
234         tree->tid = tcon.tconx.out.cnum;
235         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
236
237         printf("try a tconx with a bad device type\n");
238         tcon.tconx.in.device = "FOO";   
239         status = smb_tree_connect(tree, mem_ctx, &tcon);
240         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
241
242
243         printf("create a file using the new tid\n");
244         io.generic.level = RAW_OPEN_NTCREATEX;
245         io.ntcreatex.in.root_fid = 0;
246         io.ntcreatex.in.flags = 0;
247         io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
248         io.ntcreatex.in.create_options = 0;
249         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
250         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
251         io.ntcreatex.in.alloc_size = 0;
252         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
253         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
254         io.ntcreatex.in.security_flags = 0;
255         io.ntcreatex.in.fname = fname;
256         status = smb_raw_open(tree, mem_ctx, &io);
257         CHECK_STATUS(status, NT_STATUS_OK);
258         fnum = io.ntcreatex.out.fnum;
259
260         printf("write using the old tid\n");
261         wr.generic.level = RAW_WRITE_WRITEX;
262         wr.writex.in.fnum = fnum;
263         wr.writex.in.offset = 0;
264         wr.writex.in.wmode = 0;
265         wr.writex.in.remaining = 0;
266         wr.writex.in.count = 1;
267         wr.writex.in.data = &c;
268
269         status = smb_raw_write(cli->tree, &wr);
270         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
271
272         printf("write with the new tid\n");
273         status = smb_raw_write(tree, &wr);
274         CHECK_STATUS(status, NT_STATUS_OK);
275         CHECK_VALUE(wr.writex.out.nwritten, 1);
276
277         printf("disconnect the new tid\n");
278         status = smb_tree_disconnect(tree);
279         CHECK_STATUS(status, NT_STATUS_OK);
280
281         printf("the new tid should not now be accessible\n");
282         status = smb_raw_write(tree, &wr);
283         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
284
285         printf("the fnum should have been auto-closed\n");
286         cl.close.level = RAW_CLOSE_CLOSE;
287         cl.close.in.fnum = fnum;
288         cl.close.in.write_time = 0;
289         status = smb_raw_close(cli->tree, &cl);
290         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
291
292         /* close down the new tree */
293         talloc_free(tree);
294         
295 done:
296         return ret;
297 }
298
299
300 /*
301   test pid ops
302 */
303 static BOOL test_pid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
304 {
305         NTSTATUS status;
306         BOOL ret = True;
307         union smb_open io;
308         union smb_write wr;
309         union smb_close cl;
310         int fnum;
311         const char *fname = BASEDIR "\\test.txt";
312         char c = 1;
313         uint16_t pid1, pid2;
314
315         printf("TESTING PID HANDLING\n");
316
317         if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
318             NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
319                 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
320                 return False;
321         }
322
323         printf("create a second pid\n");
324         pid1 = cli->session->pid;
325         pid2 = pid1+1;
326
327         printf("pid1=%d pid2=%d\n", pid1, pid2);
328
329         printf("create a file using the new pid\n");
330         cli->session->pid = pid2;
331         io.generic.level = RAW_OPEN_NTCREATEX;
332         io.ntcreatex.in.root_fid = 0;
333         io.ntcreatex.in.flags = 0;
334         io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
335         io.ntcreatex.in.create_options = 0;
336         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
337         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
338         io.ntcreatex.in.alloc_size = 0;
339         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
340         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
341         io.ntcreatex.in.security_flags = 0;
342         io.ntcreatex.in.fname = fname;
343         status = smb_raw_open(cli->tree, mem_ctx, &io);
344         CHECK_STATUS(status, NT_STATUS_OK);
345         fnum = io.ntcreatex.out.fnum;
346
347         printf("write using the old pid\n");
348         cli->session->pid = pid1;
349         wr.generic.level = RAW_WRITE_WRITEX;
350         wr.writex.in.fnum = fnum;
351         wr.writex.in.offset = 0;
352         wr.writex.in.wmode = 0;
353         wr.writex.in.remaining = 0;
354         wr.writex.in.count = 1;
355         wr.writex.in.data = &c;
356
357         status = smb_raw_write(cli->tree, &wr);
358         CHECK_STATUS(status, NT_STATUS_OK);
359         CHECK_VALUE(wr.writex.out.nwritten, 1);
360
361         printf("write with the new pid\n");
362         cli->session->pid = pid2;
363         status = smb_raw_write(cli->tree, &wr);
364         CHECK_STATUS(status, NT_STATUS_OK);
365         CHECK_VALUE(wr.writex.out.nwritten, 1);
366
367         printf("exit the old pid\n");
368         cli->session->pid = pid1;
369         status = smb_raw_exit(cli->session);
370         CHECK_STATUS(status, NT_STATUS_OK);
371
372         printf("the fnum should still be accessible\n");
373         cli->session->pid = pid1;
374         status = smb_raw_write(cli->tree, &wr);
375         CHECK_STATUS(status, NT_STATUS_OK);
376         CHECK_VALUE(wr.writex.out.nwritten, 1);
377
378         printf("exit the new pid\n");
379         cli->session->pid = pid2;
380         status = smb_raw_exit(cli->session);
381         CHECK_STATUS(status, NT_STATUS_OK);
382
383         printf("the fnum should not now be accessible\n");
384         cli->session->pid = pid1;
385         status = smb_raw_write(cli->tree, &wr);
386         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
387
388         printf("the fnum should have been auto-closed\n");
389         cl.close.level = RAW_CLOSE_CLOSE;
390         cl.close.in.fnum = fnum;
391         cl.close.in.write_time = 0;
392         status = smb_raw_close(cli->tree, &cl);
393         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
394
395 done:
396         return ret;
397 }
398
399
400 /* 
401    basic testing of session/tree context calls
402 */
403 BOOL torture_raw_context(int dummy)
404 {
405         struct smbcli_state *cli;
406         BOOL ret = True;
407         TALLOC_CTX *mem_ctx;
408
409         lp_set_cmdline("use spnego", "False");
410
411         if (!torture_open_connection(&cli)) {
412                 return False;
413         }
414
415         mem_ctx = talloc_init("torture_raw_context");
416
417         if (!test_session(cli, mem_ctx)) {
418                 ret = False;
419         }
420
421         if (!test_tree(cli, mem_ctx)) {
422                 ret = False;
423         }
424
425         if (!test_pid(cli, mem_ctx)) {
426                 ret = False;
427         }
428
429         smb_raw_exit(cli->session);
430         smbcli_deltree(cli->tree, BASEDIR);
431
432         torture_close_connection(cli);
433         talloc_destroy(mem_ctx);
434
435         return ret;
436 }