r14732: fix typo noticed by derrell, thanks!
[gd/samba-autobuild/.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 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/composite/composite.h"
25 #include "libcli/smb_composite/smb_composite.h"
26 #include "lib/cmdline/popt_common.h"
27 #include "lib/events/events.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "auth/credentials/credentials.h"
31
32 #define BASEDIR "\\rawcontext"
33
34 #define CHECK_STATUS(status, correct) do { \
35         if (!NT_STATUS_EQUAL(status, correct)) { \
36                 printf("(%s) Incorrect status %s - should be %s\n", \
37                        __location__, nt_errstr(status), nt_errstr(correct)); \
38                 ret = False; \
39                 goto done; \
40         }} while (0)
41
42 #define CHECK_VALUE(v, correct) do { \
43         if ((v) != (correct)) { \
44                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
45                        __location__, #v, v, correct); \
46                 ret = False; \
47                 goto done; \
48         }} while (0)
49
50 #define CHECK_NOT_VALUE(v, correct) do { \
51         if ((v) == (correct)) { \
52                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
53                        __location__, #v, v, correct); \
54                 ret = False; \
55                 goto done; \
56         }} while (0)
57
58
59 /*
60   test session ops
61 */
62 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
63 {
64         NTSTATUS status;
65         BOOL ret = True;
66         struct smbcli_session *session;
67         struct smbcli_session *session2;
68         struct smbcli_session *session3;
69         struct smbcli_session *session4;
70         struct cli_credentials *anon_creds;
71         struct smbcli_session *sessions[15];
72         struct composite_context *composite_contexts[15];
73         struct smbcli_tree *tree;
74         struct smb_composite_sesssetup setup;
75         struct smb_composite_sesssetup setups[15];
76         union smb_open io;
77         union smb_write wr;
78         union smb_close cl;
79         int fnum;
80         const char *fname = BASEDIR "\\test.txt";
81         uint8_t c = 1;
82         int i;
83
84         printf("TESTING SESSION HANDLING\n");
85
86         if (!torture_setup_dir(cli, BASEDIR)) {
87                 return False;
88         }
89
90         printf("create a second security context on the same transport\n");
91         session = smbcli_session_init(cli->transport, mem_ctx, False);
92
93         setup.in.sesskey = cli->transport->negotiate.sesskey;
94         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
95         setup.in.workgroup = lp_workgroup();
96
97         setup.in.credentials = cmdline_credentials;
98
99         status = smb_composite_sesssetup(session, &setup);
100         CHECK_STATUS(status, NT_STATUS_OK);
101         
102         session->vuid = setup.out.vuid;
103
104         printf("create a third security context on the same transport, with vuid set\n");
105         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
106
107         session2->vuid = session->vuid;
108         setup.in.sesskey = cli->transport->negotiate.sesskey;
109         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
110         setup.in.workgroup = lp_workgroup();
111
112         setup.in.credentials = cmdline_credentials;
113
114         status = smb_composite_sesssetup(session2, &setup);
115         CHECK_STATUS(status, NT_STATUS_OK);
116
117         session2->vuid = setup.out.vuid;
118         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
119         
120         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
121                 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
122                 if (session2->vuid == session->vuid) {
123                         printf("server allows the user to re-use an existing vuid in session setup \n");
124                 }
125         } else {
126                 CHECK_NOT_VALUE(session2->vuid, session->vuid);
127         }
128         talloc_free(session2);
129
130         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
131                 printf("create a fourth security context on the same transport, without extended security\n");
132                 session3 = smbcli_session_init(cli->transport, mem_ctx, False);
133
134                 session3->vuid = session->vuid;
135                 setup.in.sesskey = cli->transport->negotiate.sesskey;
136                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
137                 setup.in.workgroup = lp_workgroup();
138         
139                 setup.in.credentials = cmdline_credentials;
140         
141
142                 status = smb_composite_sesssetup(session3, &setup);
143                 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
144
145                 printf("create a fouth anonymous security context on the same transport, without extended security\n");
146                 session4 = smbcli_session_init(cli->transport, mem_ctx, False);
147
148                 session4->vuid = session->vuid;
149                 setup.in.sesskey = cli->transport->negotiate.sesskey;
150                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
151                 setup.in.workgroup = lp_workgroup();
152                 
153                 anon_creds = cli_credentials_init(mem_ctx);
154                 cli_credentials_set_conf(anon_creds);
155                 cli_credentials_set_anonymous(anon_creds);
156
157                 setup.in.credentials = anon_creds;
158         
159                 status = smb_composite_sesssetup(session3, &setup);
160                 CHECK_STATUS(status, NT_STATUS_OK);
161
162                 talloc_free(session4);
163         }
164                 
165         printf("use the same tree as the existing connection\n");
166         tree = smbcli_tree_init(session, mem_ctx, False);
167         tree->tid = cli->tree->tid;
168
169         printf("create a file using the new vuid\n");
170         io.generic.level = RAW_OPEN_NTCREATEX;
171         io.ntcreatex.in.root_fid = 0;
172         io.ntcreatex.in.flags = 0;
173         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
174         io.ntcreatex.in.create_options = 0;
175         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
176         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
177         io.ntcreatex.in.alloc_size = 0;
178         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
179         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
180         io.ntcreatex.in.security_flags = 0;
181         io.ntcreatex.in.fname = fname;
182         status = smb_raw_open(tree, mem_ctx, &io);
183         CHECK_STATUS(status, NT_STATUS_OK);
184         fnum = io.ntcreatex.out.file.fnum;
185
186         printf("write using the old vuid\n");
187         wr.generic.level = RAW_WRITE_WRITEX;
188         wr.writex.in.file.fnum = fnum;
189         wr.writex.in.offset = 0;
190         wr.writex.in.wmode = 0;
191         wr.writex.in.remaining = 0;
192         wr.writex.in.count = 1;
193         wr.writex.in.data = &c;
194
195         status = smb_raw_write(cli->tree, &wr);
196         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
197
198         printf("write with the new vuid\n");
199         status = smb_raw_write(tree, &wr);
200         CHECK_STATUS(status, NT_STATUS_OK);
201         CHECK_VALUE(wr.writex.out.nwritten, 1);
202
203         printf("logoff the new vuid\n");
204         status = smb_raw_ulogoff(session);
205         CHECK_STATUS(status, NT_STATUS_OK);
206
207         printf("the new vuid should not now be accessible\n");
208         status = smb_raw_write(tree, &wr);
209         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
210
211         printf("second logoff for the new vuid should fail\n");
212         status = smb_raw_ulogoff(session);
213         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
214         talloc_free(session);
215
216         printf("the fnum should have been auto-closed\n");
217         cl.close.level = RAW_CLOSE_CLOSE;
218         cl.close.in.file.fnum = fnum;
219         cl.close.in.write_time = 0;
220         status = smb_raw_close(cli->tree, &cl);
221         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
222
223         printf("create %d secondary security contexts on the same transport\n", 
224                (int)ARRAY_SIZE(sessions));
225         for (i=0; i <ARRAY_SIZE(sessions); i++) {
226                 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
227                 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
228                 setups[i].in.workgroup = lp_workgroup();
229                 
230                 setups[i].in.credentials = cmdline_credentials;
231
232                 sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False);
233                 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
234
235         }
236
237
238         /* flush the queue */
239         for (i=0; i < ARRAY_SIZE(sessions); i++) {
240                 event_loop_once(composite_contexts[0]->event_ctx);
241         }
242
243         printf("finishing %d secondary security contexts on the same transport\n", 
244                (int)ARRAY_SIZE(sessions));
245         for (i=0; i< ARRAY_SIZE(sessions); i++) {
246                 status = smb_composite_sesssetup_recv(composite_contexts[i]);
247                 CHECK_STATUS(status, NT_STATUS_OK);
248                 sessions[i]->vuid = setups[i].out.vuid;
249                 printf("VUID: %d\n", sessions[i]->vuid);
250                 status = smb_raw_ulogoff(sessions[i]);
251                 CHECK_STATUS(status, NT_STATUS_OK);
252         }
253
254
255         talloc_free(tree);
256         
257 done:
258         return ret;
259 }
260
261
262 /*
263   test tree ops
264 */
265 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
266 {
267         NTSTATUS status;
268         BOOL ret = True;
269         const char *share, *host;
270         struct smbcli_tree *tree;
271         union smb_tcon tcon;
272         union smb_open io;
273         union smb_write wr;
274         union smb_close cl;
275         int fnum;
276         const char *fname = BASEDIR "\\test.txt";
277         uint8_t c = 1;
278
279         printf("TESTING TREE HANDLING\n");
280
281         if (!torture_setup_dir(cli, BASEDIR)) {
282                 return False;
283         }
284
285         share = lp_parm_string(-1, "torture", "share");
286         host  = lp_parm_string(-1, "torture", "host");
287         
288         printf("create a second tree context on the same session\n");
289         tree = smbcli_tree_init(cli->session, mem_ctx, False);
290
291         tcon.generic.level = RAW_TCON_TCONX;
292         tcon.tconx.in.flags = 0;
293         tcon.tconx.in.password = data_blob(NULL, 0);
294         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
295         tcon.tconx.in.device = "A:";    
296         status = smb_raw_tcon(tree, mem_ctx, &tcon);
297         CHECK_STATUS(status, NT_STATUS_OK);
298         
299
300         tree->tid = tcon.tconx.out.tid;
301         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
302
303         printf("try a tconx with a bad device type\n");
304         tcon.tconx.in.device = "FOO";   
305         status = smb_raw_tcon(tree, mem_ctx, &tcon);
306         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
307
308
309         printf("create a file using the new tid\n");
310         io.generic.level = RAW_OPEN_NTCREATEX;
311         io.ntcreatex.in.root_fid = 0;
312         io.ntcreatex.in.flags = 0;
313         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
314         io.ntcreatex.in.create_options = 0;
315         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
316         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
317         io.ntcreatex.in.alloc_size = 0;
318         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
319         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
320         io.ntcreatex.in.security_flags = 0;
321         io.ntcreatex.in.fname = fname;
322         status = smb_raw_open(tree, mem_ctx, &io);
323         CHECK_STATUS(status, NT_STATUS_OK);
324         fnum = io.ntcreatex.out.file.fnum;
325
326         printf("write using the old tid\n");
327         wr.generic.level = RAW_WRITE_WRITEX;
328         wr.writex.in.file.fnum = fnum;
329         wr.writex.in.offset = 0;
330         wr.writex.in.wmode = 0;
331         wr.writex.in.remaining = 0;
332         wr.writex.in.count = 1;
333         wr.writex.in.data = &c;
334
335         status = smb_raw_write(cli->tree, &wr);
336         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
337
338         printf("write with the new tid\n");
339         status = smb_raw_write(tree, &wr);
340         CHECK_STATUS(status, NT_STATUS_OK);
341         CHECK_VALUE(wr.writex.out.nwritten, 1);
342
343         printf("disconnect the new tid\n");
344         status = smb_tree_disconnect(tree);
345         CHECK_STATUS(status, NT_STATUS_OK);
346
347         printf("the new tid should not now be accessible\n");
348         status = smb_raw_write(tree, &wr);
349         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
350
351         printf("the fnum should have been auto-closed\n");
352         cl.close.level = RAW_CLOSE_CLOSE;
353         cl.close.in.file.fnum = fnum;
354         cl.close.in.write_time = 0;
355         status = smb_raw_close(cli->tree, &cl);
356         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
357
358         /* close down the new tree */
359         talloc_free(tree);
360         
361 done:
362         return ret;
363 }
364
365 /*
366   test pid ops
367   this test demonstrates that exit() only sees the PID
368   used for the open() calls
369 */
370 static BOOL test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
371 {
372         NTSTATUS status;
373         BOOL ret = True;
374         union smb_open io;
375         union smb_write wr;
376         union smb_close cl;
377         int fnum;
378         const char *fname = BASEDIR "\\test.txt";
379         uint8_t c = 1;
380         uint16_t pid1, pid2;
381
382         printf("TESTING PID HANDLING exit() only cares about open() PID\n");
383
384         if (!torture_setup_dir(cli, BASEDIR)) {
385                 return False;
386         }
387
388         printf("pid1=%d pid2=%d\n", pid1, pid2);
389
390         printf("create a file using pid1\n");
391         cli->session->pid = pid1;
392         io.generic.level = RAW_OPEN_NTCREATEX;
393         io.ntcreatex.in.root_fid = 0;
394         io.ntcreatex.in.flags = 0;
395         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
396         io.ntcreatex.in.create_options = 0;
397         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
398         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
399         io.ntcreatex.in.alloc_size = 0;
400         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
401         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
402         io.ntcreatex.in.security_flags = 0;
403         io.ntcreatex.in.fname = fname;
404         status = smb_raw_open(cli->tree, mem_ctx, &io);
405         CHECK_STATUS(status, NT_STATUS_OK);
406         fnum = io.ntcreatex.out.file.fnum;
407
408         printf("write using pid2\n");
409         cli->session->pid = pid2;
410         wr.generic.level = RAW_WRITE_WRITEX;
411         wr.writex.in.file.fnum = fnum;
412         wr.writex.in.offset = 0;
413         wr.writex.in.wmode = 0;
414         wr.writex.in.remaining = 0;
415         wr.writex.in.count = 1;
416         wr.writex.in.data = &c;
417         status = smb_raw_write(cli->tree, &wr);
418         CHECK_STATUS(status, NT_STATUS_OK);
419         CHECK_VALUE(wr.writex.out.nwritten, 1);
420
421         printf("exit pid2\n");
422         cli->session->pid = pid2;
423         status = smb_raw_exit(cli->session);
424         CHECK_STATUS(status, NT_STATUS_OK);
425
426         printf("the fnum should still be accessible via pid2\n");
427         cli->session->pid = pid2;
428         status = smb_raw_write(cli->tree, &wr);
429         CHECK_STATUS(status, NT_STATUS_OK);
430         CHECK_VALUE(wr.writex.out.nwritten, 1);
431
432         printf("exit pid2\n");
433         cli->session->pid = pid2;
434         status = smb_raw_exit(cli->session);
435         CHECK_STATUS(status, NT_STATUS_OK);
436
437         printf("the fnum should still be accessible via pid1 and pid2\n");
438         cli->session->pid = pid1;
439         status = smb_raw_write(cli->tree, &wr);
440         CHECK_STATUS(status, NT_STATUS_OK);
441         CHECK_VALUE(wr.writex.out.nwritten, 1);
442         cli->session->pid = pid2;
443         status = smb_raw_write(cli->tree, &wr);
444         CHECK_STATUS(status, NT_STATUS_OK);
445         CHECK_VALUE(wr.writex.out.nwritten, 1);
446
447         printf("exit pid1\n");
448         cli->session->pid = pid1;
449         status = smb_raw_exit(cli->session);
450         CHECK_STATUS(status, NT_STATUS_OK);
451
452         printf("the fnum should not now be accessible via pid1 or pid2\n");
453         cli->session->pid = pid1;
454         status = smb_raw_write(cli->tree, &wr);
455         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
456         cli->session->pid = pid2;
457         status = smb_raw_write(cli->tree, &wr);
458         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
459
460         printf("the fnum should have been auto-closed\n");
461         cli->session->pid = pid1;
462         cl.close.level = RAW_CLOSE_CLOSE;
463         cl.close.in.file.fnum = fnum;
464         cl.close.in.write_time = 0;
465         status = smb_raw_close(cli->tree, &cl);
466         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
467
468 done:
469         return ret;
470 }
471
472 /*
473   test pid ops with 2 sessions
474 */
475 static BOOL test_pid_2sess(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
476 {
477         NTSTATUS status;
478         BOOL ret = True;
479         struct smbcli_session *session;
480         struct smb_composite_sesssetup setup;
481         union smb_open io;
482         union smb_write wr;
483         union smb_close cl;
484         int fnum;
485         const char *fname = BASEDIR "\\test.txt";
486         uint8_t c = 1;
487         uint16_t vuid1, vuid2;
488
489         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
490
491         if (!torture_setup_dir(cli, BASEDIR)) {
492                 return False;
493         }
494
495         printf("create a second security context on the same transport\n");
496         session = smbcli_session_init(cli->transport, mem_ctx, False);
497
498         setup.in.sesskey = cli->transport->negotiate.sesskey;
499         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
500         setup.in.workgroup = lp_workgroup();
501
502         setup.in.credentials = cmdline_credentials;
503
504         status = smb_composite_sesssetup(session, &setup);
505         CHECK_STATUS(status, NT_STATUS_OK);     
506         session->vuid = setup.out.vuid;
507
508         vuid1 = cli->session->vuid;
509         vuid2 = session->vuid;
510
511         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
512
513         printf("create a file using the vuid1\n");
514         cli->session->vuid = vuid1;
515         io.generic.level = RAW_OPEN_NTCREATEX;
516         io.ntcreatex.in.root_fid = 0;
517         io.ntcreatex.in.flags = 0;
518         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
519         io.ntcreatex.in.create_options = 0;
520         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
521         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
522         io.ntcreatex.in.alloc_size = 0;
523         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
524         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
525         io.ntcreatex.in.security_flags = 0;
526         io.ntcreatex.in.fname = fname;
527         status = smb_raw_open(cli->tree, mem_ctx, &io);
528         CHECK_STATUS(status, NT_STATUS_OK);
529         fnum = io.ntcreatex.out.file.fnum;
530
531         printf("write using the vuid1 (fnum=%d)\n", fnum);
532         cli->session->vuid = vuid1;
533         wr.generic.level = RAW_WRITE_WRITEX;
534         wr.writex.in.file.fnum = fnum;
535         wr.writex.in.offset = 0;
536         wr.writex.in.wmode = 0;
537         wr.writex.in.remaining = 0;
538         wr.writex.in.count = 1;
539         wr.writex.in.data = &c;
540
541         status = smb_raw_write(cli->tree, &wr);
542         CHECK_STATUS(status, NT_STATUS_OK);
543         CHECK_VALUE(wr.writex.out.nwritten, 1);
544
545         printf("exit the pid with vuid2\n");
546         cli->session->vuid = vuid2;
547         status = smb_raw_exit(cli->session);
548         CHECK_STATUS(status, NT_STATUS_OK);
549
550         printf("the fnum should still be accessible\n");
551         cli->session->vuid = vuid1;
552         status = smb_raw_write(cli->tree, &wr);
553         CHECK_STATUS(status, NT_STATUS_OK);
554         CHECK_VALUE(wr.writex.out.nwritten, 1);
555
556         printf("exit the pid with vuid1\n");
557         cli->session->vuid = vuid1;
558         status = smb_raw_exit(cli->session);
559         CHECK_STATUS(status, NT_STATUS_OK);
560
561         printf("the fnum should not now be accessible\n");
562         status = smb_raw_write(cli->tree, &wr);
563         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
564
565         printf("the fnum should have been auto-closed\n");
566         cl.close.level = RAW_CLOSE_CLOSE;
567         cl.close.in.file.fnum = fnum;
568         cl.close.in.write_time = 0;
569         status = smb_raw_close(cli->tree, &cl);
570         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
571
572 done:
573         return ret;
574 }
575
576 /*
577   test pid ops with 2 tcons
578 */
579 static BOOL test_pid_2tcon(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
580 {
581         NTSTATUS status;
582         BOOL ret = True;
583         const char *share, *host;
584         struct smbcli_tree *tree;
585         union smb_tcon tcon;
586         union smb_open io;
587         union smb_write wr;
588         union smb_close cl;
589         int fnum1, fnum2;
590         const char *fname1 = BASEDIR "\\test1.txt";
591         const char *fname2 = BASEDIR "\\test2.txt";
592         uint8_t c = 1;
593         uint16_t tid1, tid2;
594
595         printf("TESTING PID HANDLING WITH 2 TCONS\n");
596
597         if (!torture_setup_dir(cli, BASEDIR)) {
598                 return False;
599         }
600
601         share = lp_parm_string(-1, "torture", "share");
602         host  = lp_parm_string(-1, "torture", "host");
603         
604         printf("create a second tree context on the same session\n");
605         tree = smbcli_tree_init(cli->session, mem_ctx, False);
606
607         tcon.generic.level = RAW_TCON_TCONX;
608         tcon.tconx.in.flags = 0;
609         tcon.tconx.in.password = data_blob(NULL, 0);
610         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
611         tcon.tconx.in.device = "A:";    
612         status = smb_raw_tcon(tree, mem_ctx, &tcon);
613         CHECK_STATUS(status, NT_STATUS_OK);     
614
615         tree->tid = tcon.tconx.out.tid;
616
617         tid1 = cli->tree->tid;
618         tid2 = tree->tid;
619         printf("tid1=%d tid2=%d\n", tid1, tid2);
620
621         printf("create a file using the tid1\n");
622         cli->tree->tid = tid1;
623         io.generic.level = RAW_OPEN_NTCREATEX;
624         io.ntcreatex.in.root_fid = 0;
625         io.ntcreatex.in.flags = 0;
626         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
627         io.ntcreatex.in.create_options = 0;
628         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
629         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
630         io.ntcreatex.in.alloc_size = 0;
631         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
632         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
633         io.ntcreatex.in.security_flags = 0;
634         io.ntcreatex.in.fname = fname1;
635         status = smb_raw_open(cli->tree, mem_ctx, &io);
636         CHECK_STATUS(status, NT_STATUS_OK);
637         fnum1 = io.ntcreatex.out.file.fnum;
638
639         printf("write using the tid1\n");
640         wr.generic.level = RAW_WRITE_WRITEX;
641         wr.writex.in.file.fnum = fnum1;
642         wr.writex.in.offset = 0;
643         wr.writex.in.wmode = 0;
644         wr.writex.in.remaining = 0;
645         wr.writex.in.count = 1;
646         wr.writex.in.data = &c;
647
648         status = smb_raw_write(cli->tree, &wr);
649         CHECK_STATUS(status, NT_STATUS_OK);
650         CHECK_VALUE(wr.writex.out.nwritten, 1);
651
652         printf("create a file using the tid2\n");
653         cli->tree->tid = tid2;
654         io.generic.level = RAW_OPEN_NTCREATEX;
655         io.ntcreatex.in.root_fid = 0;
656         io.ntcreatex.in.flags = 0;
657         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
658         io.ntcreatex.in.create_options = 0;
659         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
660         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
661         io.ntcreatex.in.alloc_size = 0;
662         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
663         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
664         io.ntcreatex.in.security_flags = 0;
665         io.ntcreatex.in.fname = fname2;
666         status = smb_raw_open(cli->tree, mem_ctx, &io);
667         CHECK_STATUS(status, NT_STATUS_OK);
668         fnum2 = io.ntcreatex.out.file.fnum;
669
670         printf("write using the tid2\n");
671         wr.generic.level = RAW_WRITE_WRITEX;
672         wr.writex.in.file.fnum = fnum2;
673         wr.writex.in.offset = 0;
674         wr.writex.in.wmode = 0;
675         wr.writex.in.remaining = 0;
676         wr.writex.in.count = 1;
677         wr.writex.in.data = &c;
678
679         status = smb_raw_write(cli->tree, &wr);
680         CHECK_STATUS(status, NT_STATUS_OK);
681         CHECK_VALUE(wr.writex.out.nwritten, 1);
682
683         printf("exit the pid\n");
684         status = smb_raw_exit(cli->session);
685         CHECK_STATUS(status, NT_STATUS_OK);
686
687         printf("the fnum1 on tid1 should not be accessible\n");
688         cli->tree->tid = tid1;
689         wr.writex.in.file.fnum = fnum1;
690         status = smb_raw_write(cli->tree, &wr);
691         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
692
693         printf("the fnum1 on tid1 should have been auto-closed\n");
694         cl.close.level = RAW_CLOSE_CLOSE;
695         cl.close.in.file.fnum = fnum1;
696         cl.close.in.write_time = 0;
697         status = smb_raw_close(cli->tree, &cl);
698         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
699
700         printf("the fnum2 on tid2 should not be accessible\n");
701         cli->tree->tid = tid2;
702         wr.writex.in.file.fnum = fnum2;
703         status = smb_raw_write(cli->tree, &wr);
704         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
705
706         printf("the fnum2 on tid2 should have been auto-closed\n");
707         cl.close.level = RAW_CLOSE_CLOSE;
708         cl.close.in.file.fnum = fnum2;
709         cl.close.in.write_time = 0;
710         status = smb_raw_close(cli->tree, &cl);
711         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
712
713 done:
714         return ret;
715 }
716
717
718 /* 
719    basic testing of session/tree context calls
720 */
721 static BOOL torture_raw_context_int(void)
722 {
723         struct smbcli_state *cli;
724         BOOL ret = True;
725         TALLOC_CTX *mem_ctx;
726
727         if (!torture_open_connection(&cli)) {
728                 return False;
729         }
730
731         mem_ctx = talloc_init("torture_raw_context");
732
733         ret &= test_session(cli, mem_ctx);
734         ret &= test_tree(cli, mem_ctx);
735         ret &= test_pid_exit_only_sees_open(cli, mem_ctx);
736         ret &= test_pid_2sess(cli, mem_ctx);
737         ret &= test_pid_2tcon(cli, mem_ctx);
738
739         smb_raw_exit(cli->session);
740         smbcli_deltree(cli->tree, BASEDIR);
741
742         torture_close_connection(cli);
743         talloc_free(mem_ctx);
744
745         return ret;
746 }
747 /* 
748    basic testing of session/tree context calls
749 */
750 BOOL torture_raw_context(struct torture_context *torture)
751 {
752         BOOL ret = True;
753         if (lp_use_spnego()) {
754                 ret &= torture_raw_context_int();
755                 lp_set_cmdline("use spnego", "False");
756         }
757
758         ret &= torture_raw_context_int();
759
760         return ret;
761 }