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