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