r6028: A MAJOR update to intergrate the new credentails system fully with
[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 "libcli/raw/libcliraw.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "libcli/composite/composite.h"
25 #include "lib/cmdline/popt_common.h"
26
27 #define BASEDIR "\\rawcontext"
28
29 #define CHECK_STATUS(status, correct) do { \
30         if (!NT_STATUS_EQUAL(status, correct)) { \
31                 printf("(%s) Incorrect status %s - should be %s\n", \
32                        __location__, nt_errstr(status), nt_errstr(correct)); \
33                 ret = False; \
34                 goto done; \
35         }} while (0)
36
37 #define CHECK_VALUE(v, correct) do { \
38         if ((v) != (correct)) { \
39                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
40                        __location__, #v, v, correct); \
41                 ret = False; \
42                 goto done; \
43         }} while (0)
44
45 #define CHECK_NOT_VALUE(v, correct) do { \
46         if ((v) == (correct)) { \
47                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
48                        __location__, #v, v, correct); \
49                 ret = False; \
50                 goto done; \
51         }} while (0)
52
53
54 /*
55   test session ops
56 */
57 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
58 {
59         NTSTATUS status;
60         BOOL ret = True;
61         struct smbcli_session *session;
62         struct smbcli_session *session2;
63         struct smbcli_session *session3;
64         struct smbcli_tree *tree;
65         struct smb_composite_sesssetup setup;
66         union smb_open io;
67         union smb_write wr;
68         union smb_close cl;
69         int fnum;
70         const char *fname = BASEDIR "\\test.txt";
71         uint8_t c = 1;
72
73         printf("TESTING SESSION HANDLING\n");
74
75         if (!torture_setup_dir(cli, BASEDIR)) {
76                 return False;
77         }
78
79         printf("create a second security context on the same transport\n");
80         session = smbcli_session_init(cli->transport, mem_ctx, False);
81
82         setup.in.sesskey = cli->transport->negotiate.sesskey;
83         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
84         setup.in.workgroup = lp_workgroup();
85
86         setup.in.credentials = cmdline_credentials;
87
88         status = smb_composite_sesssetup(session, &setup);
89         CHECK_STATUS(status, NT_STATUS_OK);
90
91         session->vuid = setup.out.vuid;
92
93         printf("create a third security context on the same transport, with vuid set\n");
94         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
95
96         session2->vuid = session->vuid;
97         setup.in.sesskey = cli->transport->negotiate.sesskey;
98         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
99         setup.in.workgroup = lp_workgroup();
100
101         setup.in.credentials = cmdline_credentials;
102
103         status = smb_composite_sesssetup(session2, &setup);
104         CHECK_STATUS(status, NT_STATUS_OK);
105
106         session2->vuid = setup.out.vuid;
107         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
108         
109         CHECK_NOT_VALUE(session->vuid, session2->vuid);
110         talloc_free(session2);
111
112         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
113                 printf("create a fourth security context on the same transport, without extended security\n");
114                 session3 = smbcli_session_init(cli->transport, mem_ctx, False);
115
116                 session3->vuid = session->vuid;
117                 setup.in.sesskey = cli->transport->negotiate.sesskey;
118                 setup.in.capabilities = 0; /* force a non extended security login (should fail) */
119                 setup.in.workgroup = lp_workgroup();
120         
121                 setup.in.credentials = cmdline_credentials;
122         
123
124                 status = smb_composite_sesssetup(session3, &setup);
125                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
126
127                 talloc_free(session3);
128         }
129                 
130         printf("use the same tree as the existing connection\n");
131         tree = smbcli_tree_init(session, mem_ctx, False);
132         tree->tid = cli->tree->tid;
133
134         printf("create a file using the new vuid\n");
135         io.generic.level = RAW_OPEN_NTCREATEX;
136         io.ntcreatex.in.root_fid = 0;
137         io.ntcreatex.in.flags = 0;
138         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
139         io.ntcreatex.in.create_options = 0;
140         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
141         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
142         io.ntcreatex.in.alloc_size = 0;
143         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
144         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
145         io.ntcreatex.in.security_flags = 0;
146         io.ntcreatex.in.fname = fname;
147         status = smb_raw_open(tree, mem_ctx, &io);
148         CHECK_STATUS(status, NT_STATUS_OK);
149         fnum = io.ntcreatex.out.fnum;
150
151         printf("write using the old vuid\n");
152         wr.generic.level = RAW_WRITE_WRITEX;
153         wr.writex.in.fnum = fnum;
154         wr.writex.in.offset = 0;
155         wr.writex.in.wmode = 0;
156         wr.writex.in.remaining = 0;
157         wr.writex.in.count = 1;
158         wr.writex.in.data = &c;
159
160         status = smb_raw_write(cli->tree, &wr);
161         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
162
163         printf("write with the new vuid\n");
164         status = smb_raw_write(tree, &wr);
165         CHECK_STATUS(status, NT_STATUS_OK);
166         CHECK_VALUE(wr.writex.out.nwritten, 1);
167
168         printf("logoff the new vuid\n");
169         status = smb_raw_ulogoff(session);
170         CHECK_STATUS(status, NT_STATUS_OK);
171         talloc_free(session);
172
173         printf("the new vuid should not now be accessible\n");
174         status = smb_raw_write(tree, &wr);
175         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
176
177         printf("the fnum should have been auto-closed\n");
178         cl.close.level = RAW_CLOSE_CLOSE;
179         cl.close.in.fnum = fnum;
180         cl.close.in.write_time = 0;
181         status = smb_raw_close(cli->tree, &cl);
182         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
183
184         talloc_free(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         const 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         uint8_t c = 1;
207
208         printf("TESTING TREE HANDLING\n");
209
210         if (!torture_setup_dir(cli, BASEDIR)) {
211                 return False;
212         }
213
214         share = lp_parm_string(-1, "torture", "share");
215         
216         printf("create a second tree context on the same session\n");
217         tree = smbcli_tree_init(cli->session, mem_ctx, False);
218
219         tcon.generic.level = RAW_TCON_TCONX;
220         tcon.tconx.in.flags = 0;
221         tcon.tconx.in.password = data_blob(NULL, 0);
222         tcon.tconx.in.path = share;
223         tcon.tconx.in.device = "A:";    
224         status = smb_tree_connect(tree, mem_ctx, &tcon);
225         CHECK_STATUS(status, NT_STATUS_OK);
226
227         tree->tid = tcon.tconx.out.tid;
228         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
229
230         printf("try a tconx with a bad device type\n");
231         tcon.tconx.in.device = "FOO";   
232         status = smb_tree_connect(tree, mem_ctx, &tcon);
233         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
234
235
236         printf("create a file using the new tid\n");
237         io.generic.level = RAW_OPEN_NTCREATEX;
238         io.ntcreatex.in.root_fid = 0;
239         io.ntcreatex.in.flags = 0;
240         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
241         io.ntcreatex.in.create_options = 0;
242         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
243         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
244         io.ntcreatex.in.alloc_size = 0;
245         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
246         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
247         io.ntcreatex.in.security_flags = 0;
248         io.ntcreatex.in.fname = fname;
249         status = smb_raw_open(tree, mem_ctx, &io);
250         CHECK_STATUS(status, NT_STATUS_OK);
251         fnum = io.ntcreatex.out.fnum;
252
253         printf("write using the old tid\n");
254         wr.generic.level = RAW_WRITE_WRITEX;
255         wr.writex.in.fnum = fnum;
256         wr.writex.in.offset = 0;
257         wr.writex.in.wmode = 0;
258         wr.writex.in.remaining = 0;
259         wr.writex.in.count = 1;
260         wr.writex.in.data = &c;
261
262         status = smb_raw_write(cli->tree, &wr);
263         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
264
265         printf("write with the new tid\n");
266         status = smb_raw_write(tree, &wr);
267         CHECK_STATUS(status, NT_STATUS_OK);
268         CHECK_VALUE(wr.writex.out.nwritten, 1);
269
270         printf("disconnect the new tid\n");
271         status = smb_tree_disconnect(tree);
272         CHECK_STATUS(status, NT_STATUS_OK);
273
274         printf("the new tid should not now be accessible\n");
275         status = smb_raw_write(tree, &wr);
276         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
277
278         printf("the fnum should have been auto-closed\n");
279         cl.close.level = RAW_CLOSE_CLOSE;
280         cl.close.in.fnum = fnum;
281         cl.close.in.write_time = 0;
282         status = smb_raw_close(cli->tree, &cl);
283         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
284
285         /* close down the new tree */
286         talloc_free(tree);
287         
288 done:
289         return ret;
290 }
291
292
293 /*
294   test pid ops
295 */
296 static BOOL test_pid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
297 {
298         NTSTATUS status;
299         BOOL ret = True;
300         union smb_open io;
301         union smb_write wr;
302         union smb_close cl;
303         int fnum;
304         const char *fname = BASEDIR "\\test.txt";
305         uint8_t c = 1;
306         uint16_t pid1, pid2;
307
308         printf("TESTING PID HANDLING\n");
309
310         if (!torture_setup_dir(cli, BASEDIR)) {
311                 return False;
312         }
313
314         printf("create a second pid\n");
315         pid1 = cli->session->pid;
316         pid2 = pid1+1;
317
318         printf("pid1=%d pid2=%d\n", pid1, pid2);
319
320         printf("create a file using the new pid\n");
321         cli->session->pid = pid2;
322         io.generic.level = RAW_OPEN_NTCREATEX;
323         io.ntcreatex.in.root_fid = 0;
324         io.ntcreatex.in.flags = 0;
325         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
326         io.ntcreatex.in.create_options = 0;
327         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
328         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
329         io.ntcreatex.in.alloc_size = 0;
330         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
331         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
332         io.ntcreatex.in.security_flags = 0;
333         io.ntcreatex.in.fname = fname;
334         status = smb_raw_open(cli->tree, mem_ctx, &io);
335         CHECK_STATUS(status, NT_STATUS_OK);
336         fnum = io.ntcreatex.out.fnum;
337
338         printf("write using the old pid\n");
339         cli->session->pid = pid1;
340         wr.generic.level = RAW_WRITE_WRITEX;
341         wr.writex.in.fnum = fnum;
342         wr.writex.in.offset = 0;
343         wr.writex.in.wmode = 0;
344         wr.writex.in.remaining = 0;
345         wr.writex.in.count = 1;
346         wr.writex.in.data = &c;
347
348         status = smb_raw_write(cli->tree, &wr);
349         CHECK_STATUS(status, NT_STATUS_OK);
350         CHECK_VALUE(wr.writex.out.nwritten, 1);
351
352         printf("write with the new pid\n");
353         cli->session->pid = pid2;
354         status = smb_raw_write(cli->tree, &wr);
355         CHECK_STATUS(status, NT_STATUS_OK);
356         CHECK_VALUE(wr.writex.out.nwritten, 1);
357
358         printf("exit the old pid\n");
359         cli->session->pid = pid1;
360         status = smb_raw_exit(cli->session);
361         CHECK_STATUS(status, NT_STATUS_OK);
362
363         printf("the fnum should still be accessible\n");
364         cli->session->pid = pid1;
365         status = smb_raw_write(cli->tree, &wr);
366         CHECK_STATUS(status, NT_STATUS_OK);
367         CHECK_VALUE(wr.writex.out.nwritten, 1);
368
369         printf("exit the new pid\n");
370         cli->session->pid = pid2;
371         status = smb_raw_exit(cli->session);
372         CHECK_STATUS(status, NT_STATUS_OK);
373
374         printf("the fnum should not now be accessible\n");
375         cli->session->pid = pid1;
376         status = smb_raw_write(cli->tree, &wr);
377         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
378
379         printf("the fnum should have been auto-closed\n");
380         cl.close.level = RAW_CLOSE_CLOSE;
381         cl.close.in.fnum = fnum;
382         cl.close.in.write_time = 0;
383         status = smb_raw_close(cli->tree, &cl);
384         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
385
386 done:
387         return ret;
388 }
389
390
391 /* 
392    basic testing of session/tree context calls
393 */
394 BOOL torture_raw_context(void)
395 {
396         struct smbcli_state *cli;
397         BOOL ret = True;
398         TALLOC_CTX *mem_ctx;
399
400         lp_set_cmdline("use spnego", "False");
401
402         if (!torture_open_connection(&cli)) {
403                 return False;
404         }
405
406         mem_ctx = talloc_init("torture_raw_context");
407
408         if (!test_session(cli, mem_ctx)) {
409                 ret = False;
410         }
411
412         if (!test_tree(cli, mem_ctx)) {
413                 ret = False;
414         }
415
416         if (!test_pid(cli, mem_ctx)) {
417                 ret = False;
418         }
419
420         smb_raw_exit(cli->session);
421         smbcli_deltree(cli->tree, BASEDIR);
422
423         torture_close_connection(cli);
424         talloc_free(mem_ctx);
425
426         return ret;
427 }