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