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