90f4b811317d61c2601241d42a3866dfbf1f148b
[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 /*
367   test pid ops
368 */
369 static BOOL test_pid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
370 {
371         NTSTATUS status;
372         BOOL ret = True;
373         union smb_open io;
374         union smb_write wr;
375         union smb_close cl;
376         int fnum;
377         const char *fname = BASEDIR "\\test.txt";
378         uint8_t c = 1;
379         uint16_t pid1, pid2;
380
381         printf("TESTING PID HANDLING\n");
382
383         if (!torture_setup_dir(cli, BASEDIR)) {
384                 return False;
385         }
386
387         printf("create a second pid\n");
388         pid1 = cli->session->pid;
389         pid2 = pid1+1;
390
391         printf("pid1=%d pid2=%d\n", pid1, pid2);
392
393         printf("create a file using the new pid\n");
394         cli->session->pid = pid2;
395         io.generic.level = RAW_OPEN_NTCREATEX;
396         io.ntcreatex.in.root_fid = 0;
397         io.ntcreatex.in.flags = 0;
398         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
399         io.ntcreatex.in.create_options = 0;
400         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
401         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
402         io.ntcreatex.in.alloc_size = 0;
403         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
404         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
405         io.ntcreatex.in.security_flags = 0;
406         io.ntcreatex.in.fname = fname;
407         status = smb_raw_open(cli->tree, mem_ctx, &io);
408         CHECK_STATUS(status, NT_STATUS_OK);
409         fnum = io.ntcreatex.out.file.fnum;
410
411         printf("write using the old pid\n");
412         cli->session->pid = pid1;
413         wr.generic.level = RAW_WRITE_WRITEX;
414         wr.writex.in.file.fnum = fnum;
415         wr.writex.in.offset = 0;
416         wr.writex.in.wmode = 0;
417         wr.writex.in.remaining = 0;
418         wr.writex.in.count = 1;
419         wr.writex.in.data = &c;
420
421         status = smb_raw_write(cli->tree, &wr);
422         CHECK_STATUS(status, NT_STATUS_OK);
423         CHECK_VALUE(wr.writex.out.nwritten, 1);
424
425         printf("write with the new pid\n");
426         cli->session->pid = pid2;
427         status = smb_raw_write(cli->tree, &wr);
428         CHECK_STATUS(status, NT_STATUS_OK);
429         CHECK_VALUE(wr.writex.out.nwritten, 1);
430
431         printf("exit the old pid\n");
432         cli->session->pid = pid1;
433         status = smb_raw_exit(cli->session);
434         CHECK_STATUS(status, NT_STATUS_OK);
435
436         printf("the fnum should still be accessible\n");
437         cli->session->pid = pid1;
438         status = smb_raw_write(cli->tree, &wr);
439         CHECK_STATUS(status, NT_STATUS_OK);
440         CHECK_VALUE(wr.writex.out.nwritten, 1);
441
442         printf("exit the new pid\n");
443         cli->session->pid = pid2;
444         status = smb_raw_exit(cli->session);
445         CHECK_STATUS(status, NT_STATUS_OK);
446
447         printf("the fnum should not now be accessible\n");
448         cli->session->pid = pid1;
449         status = smb_raw_write(cli->tree, &wr);
450         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
451
452         printf("the fnum should have been auto-closed\n");
453         cl.close.level = RAW_CLOSE_CLOSE;
454         cl.close.in.file.fnum = fnum;
455         cl.close.in.write_time = 0;
456         status = smb_raw_close(cli->tree, &cl);
457         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
458
459 done:
460         return ret;
461 }
462
463 /*
464   test pid ops with 2 sessions
465 */
466 static BOOL test_pid_2sess(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
467 {
468         NTSTATUS status;
469         BOOL ret = True;
470         struct smbcli_session *session;
471         struct smb_composite_sesssetup setup;
472         union smb_open io;
473         union smb_write wr;
474         union smb_close cl;
475         int fnum;
476         const char *fname = BASEDIR "\\test.txt";
477         uint8_t c = 1;
478         uint16_t vuid1, vuid2;
479
480         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
481
482         if (!torture_setup_dir(cli, BASEDIR)) {
483                 return False;
484         }
485
486         printf("create a second security context on the same transport\n");
487         session = smbcli_session_init(cli->transport, mem_ctx, False);
488
489         setup.in.sesskey = cli->transport->negotiate.sesskey;
490         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
491         setup.in.workgroup = lp_workgroup();
492
493         setup.in.credentials = cmdline_credentials;
494
495         status = smb_composite_sesssetup(session, &setup);
496         CHECK_STATUS(status, NT_STATUS_OK);     
497         session->vuid = setup.out.vuid;
498
499         vuid1 = cli->session->vuid;
500         vuid2 = session->vuid;
501
502         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
503
504         printf("create a file using the vuid1\n");
505         cli->session->vuid = vuid1;
506         io.generic.level = RAW_OPEN_NTCREATEX;
507         io.ntcreatex.in.root_fid = 0;
508         io.ntcreatex.in.flags = 0;
509         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
510         io.ntcreatex.in.create_options = 0;
511         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
512         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
513         io.ntcreatex.in.alloc_size = 0;
514         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
515         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
516         io.ntcreatex.in.security_flags = 0;
517         io.ntcreatex.in.fname = fname;
518         status = smb_raw_open(cli->tree, mem_ctx, &io);
519         CHECK_STATUS(status, NT_STATUS_OK);
520         fnum = io.ntcreatex.out.file.fnum;
521
522         printf("write using the vuid1 (fnum=%d)\n", fnum);
523         cli->session->vuid = vuid1;
524         wr.generic.level = RAW_WRITE_WRITEX;
525         wr.writex.in.file.fnum = fnum;
526         wr.writex.in.offset = 0;
527         wr.writex.in.wmode = 0;
528         wr.writex.in.remaining = 0;
529         wr.writex.in.count = 1;
530         wr.writex.in.data = &c;
531
532         status = smb_raw_write(cli->tree, &wr);
533         CHECK_STATUS(status, NT_STATUS_OK);
534         CHECK_VALUE(wr.writex.out.nwritten, 1);
535
536         printf("exit the pid with vuid2\n");
537         cli->session->vuid = vuid2;
538         status = smb_raw_exit(cli->session);
539         CHECK_STATUS(status, NT_STATUS_OK);
540
541         printf("the fnum should still be accessible\n");
542         cli->session->vuid = vuid1;
543         status = smb_raw_write(cli->tree, &wr);
544         CHECK_STATUS(status, NT_STATUS_OK);
545         CHECK_VALUE(wr.writex.out.nwritten, 1);
546
547         printf("exit the pid with vuid1\n");
548         cli->session->vuid = vuid1;
549         status = smb_raw_exit(cli->session);
550         CHECK_STATUS(status, NT_STATUS_OK);
551
552         printf("the fnum should not now be accessible\n");
553         status = smb_raw_write(cli->tree, &wr);
554         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
555
556         printf("the fnum should have been auto-closed\n");
557         cl.close.level = RAW_CLOSE_CLOSE;
558         cl.close.in.file.fnum = fnum;
559         cl.close.in.write_time = 0;
560         status = smb_raw_close(cli->tree, &cl);
561         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
562
563 done:
564         return ret;
565 }
566
567 /*
568   test pid ops with 2 tcons
569 */
570 static BOOL test_pid_2tcon(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
571 {
572         NTSTATUS status;
573         BOOL ret = True;
574         const char *share, *host;
575         struct smbcli_tree *tree;
576         union smb_tcon tcon;
577         union smb_open io;
578         union smb_write wr;
579         union smb_close cl;
580         int fnum1, fnum2;
581         const char *fname1 = BASEDIR "\\test1.txt";
582         const char *fname2 = BASEDIR "\\test2.txt";
583         uint8_t c = 1;
584         uint16_t tid1, tid2;
585
586         printf("TESTING PID HANDLING WITH 2 TCONS\n");
587
588         if (!torture_setup_dir(cli, BASEDIR)) {
589                 return False;
590         }
591
592         share = lp_parm_string(-1, "torture", "share");
593         host  = lp_parm_string(-1, "torture", "host");
594         
595         printf("create a second tree context on the same session\n");
596         tree = smbcli_tree_init(cli->session, mem_ctx, False);
597
598         tcon.generic.level = RAW_TCON_TCONX;
599         tcon.tconx.in.flags = 0;
600         tcon.tconx.in.password = data_blob(NULL, 0);
601         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
602         tcon.tconx.in.device = "A:";    
603         status = smb_raw_tcon(tree, mem_ctx, &tcon);
604         CHECK_STATUS(status, NT_STATUS_OK);     
605
606         tree->tid = tcon.tconx.out.tid;
607
608         tid1 = cli->tree->tid;
609         tid2 = tree->tid;
610         printf("tid1=%d tid2=%d\n", tid1, tid2);
611
612         printf("create a file using the tid1\n");
613         cli->tree->tid = tid1;
614         io.generic.level = RAW_OPEN_NTCREATEX;
615         io.ntcreatex.in.root_fid = 0;
616         io.ntcreatex.in.flags = 0;
617         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
618         io.ntcreatex.in.create_options = 0;
619         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
620         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
621         io.ntcreatex.in.alloc_size = 0;
622         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
623         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
624         io.ntcreatex.in.security_flags = 0;
625         io.ntcreatex.in.fname = fname1;
626         status = smb_raw_open(cli->tree, mem_ctx, &io);
627         CHECK_STATUS(status, NT_STATUS_OK);
628         fnum1 = io.ntcreatex.out.file.fnum;
629
630         printf("write using the tid1\n");
631         wr.generic.level = RAW_WRITE_WRITEX;
632         wr.writex.in.file.fnum = fnum1;
633         wr.writex.in.offset = 0;
634         wr.writex.in.wmode = 0;
635         wr.writex.in.remaining = 0;
636         wr.writex.in.count = 1;
637         wr.writex.in.data = &c;
638
639         status = smb_raw_write(cli->tree, &wr);
640         CHECK_STATUS(status, NT_STATUS_OK);
641         CHECK_VALUE(wr.writex.out.nwritten, 1);
642
643         printf("create a file using the tid2\n");
644         cli->tree->tid = tid2;
645         io.generic.level = RAW_OPEN_NTCREATEX;
646         io.ntcreatex.in.root_fid = 0;
647         io.ntcreatex.in.flags = 0;
648         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
649         io.ntcreatex.in.create_options = 0;
650         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
651         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
652         io.ntcreatex.in.alloc_size = 0;
653         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
654         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
655         io.ntcreatex.in.security_flags = 0;
656         io.ntcreatex.in.fname = fname2;
657         status = smb_raw_open(cli->tree, mem_ctx, &io);
658         CHECK_STATUS(status, NT_STATUS_OK);
659         fnum2 = io.ntcreatex.out.file.fnum;
660
661         printf("write using the tid2\n");
662         wr.generic.level = RAW_WRITE_WRITEX;
663         wr.writex.in.file.fnum = fnum2;
664         wr.writex.in.offset = 0;
665         wr.writex.in.wmode = 0;
666         wr.writex.in.remaining = 0;
667         wr.writex.in.count = 1;
668         wr.writex.in.data = &c;
669
670         status = smb_raw_write(cli->tree, &wr);
671         CHECK_STATUS(status, NT_STATUS_OK);
672         CHECK_VALUE(wr.writex.out.nwritten, 1);
673
674         printf("exit the pid\n");
675         status = smb_raw_exit(cli->session);
676         CHECK_STATUS(status, NT_STATUS_OK);
677
678         printf("the fnum1 on tid1 should not be accessible\n");
679         cli->tree->tid = tid1;
680         wr.writex.in.file.fnum = fnum1;
681         status = smb_raw_write(cli->tree, &wr);
682         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
683
684         printf("the fnum1 on tid1 should have been auto-closed\n");
685         cl.close.level = RAW_CLOSE_CLOSE;
686         cl.close.in.file.fnum = fnum1;
687         cl.close.in.write_time = 0;
688         status = smb_raw_close(cli->tree, &cl);
689         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
690
691         printf("the fnum2 on tid2 should not be accessible\n");
692         cli->tree->tid = tid2;
693         wr.writex.in.file.fnum = fnum2;
694         status = smb_raw_write(cli->tree, &wr);
695         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
696
697         printf("the fnum2 on tid2 should have been auto-closed\n");
698         cl.close.level = RAW_CLOSE_CLOSE;
699         cl.close.in.file.fnum = fnum2;
700         cl.close.in.write_time = 0;
701         status = smb_raw_close(cli->tree, &cl);
702         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
703
704 done:
705         return ret;
706 }
707
708
709 /* 
710    basic testing of session/tree context calls
711 */
712 static BOOL torture_raw_context_int(void)
713 {
714         struct smbcli_state *cli;
715         BOOL ret = True;
716         TALLOC_CTX *mem_ctx;
717
718         if (!torture_open_connection(&cli)) {
719                 return False;
720         }
721
722         mem_ctx = talloc_init("torture_raw_context");
723
724         ret &= test_session(cli, mem_ctx);
725         ret &= test_tree(cli, mem_ctx);
726         ret &= test_pid(cli, mem_ctx);
727         ret &= test_pid_2sess(cli, mem_ctx);
728         ret &= test_pid_2tcon(cli, mem_ctx);
729
730         smb_raw_exit(cli->session);
731         smbcli_deltree(cli->tree, BASEDIR);
732
733         torture_close_connection(cli);
734         talloc_free(mem_ctx);
735
736         return ret;
737 }
738 /* 
739    basic testing of session/tree context calls
740 */
741 BOOL torture_raw_context(void)
742 {
743         BOOL ret = True;
744         if (lp_use_spnego()) {
745                 ret &= torture_raw_context_int();
746                 lp_set_cmdline("use spnego", "False");
747         }
748
749         ret &= torture_raw_context_int();
750
751         return ret;
752 }