tests: Check symlinks are readable as reparse points
[samba.git] / source3 / torture / test_chain3.c
blob5320ef898f0b3ef1933f4c309b2b230948c95e7a
1 /*
2 Unix SMB/CIFS implementation.
3 Test smbd chain routines
5 Copyright (C) Volker Lendecke 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "torture/proto.h"
23 #include "libsmb/libsmb.h"
24 #include "system/filesys.h"
25 #include "async_smb.h"
26 #include "lib/util/tevent_ntstatus.h"
27 #include "libcli/security/security.h"
28 #include "libcli/smb/smbXcli_base.h"
30 struct chain3_andx_state {
31 uint16_t fnum;
32 size_t written;
33 char str[6];
36 static void chain3_andx_open_done(struct tevent_req *subreq);
37 static void chain3_andx_write_done(struct tevent_req *subreq);
38 static void chain3_andx_close_done(struct tevent_req *subreq);
40 static struct tevent_req *chain3_andx_send(TALLOC_CTX *mem_ctx,
41 struct tevent_context *ev,
42 struct cli_state *cli,
43 const char *fname)
45 struct tevent_req *req, *subreq;
46 struct tevent_req *smbreqs[3];
47 struct chain3_andx_state *state;
48 NTSTATUS status;
50 req = tevent_req_create(mem_ctx, &state, struct chain3_andx_state);
51 if (req == NULL) {
52 return NULL;
55 strlcpy(state->str, "hello", sizeof(state->str));
57 subreq = cli_openx_create(state, ev, cli, fname,
58 O_CREAT|O_RDWR, 0, &smbreqs[0]);
59 if (tevent_req_nomem(subreq, req)) {
60 return tevent_req_post(req, ev);
62 tevent_req_set_callback(subreq, chain3_andx_open_done, req);
64 subreq = cli_write_andx_create(state, ev, cli, 0, 0,
65 (const uint8_t *)state->str, 0,
66 strlen(state->str)+1,
67 smbreqs, 1, &smbreqs[1]);
68 if (tevent_req_nomem(subreq, req)) {
69 return tevent_req_post(req, ev);
71 tevent_req_set_callback(subreq, chain3_andx_write_done, req);
73 subreq = cli_smb1_close_create(state, ev, cli, 0, &smbreqs[2]);
74 if (tevent_req_nomem(subreq, req)) {
75 return tevent_req_post(req, ev);
77 tevent_req_set_callback(subreq, chain3_andx_close_done, req);
79 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
80 if (tevent_req_nterror(req, status)) {
81 return tevent_req_post(req, ev);
83 return req;
86 static void chain3_andx_open_done(struct tevent_req *subreq)
88 struct tevent_req *req = tevent_req_callback_data(
89 subreq, struct tevent_req);
90 struct chain3_andx_state *state = tevent_req_data(
91 req, struct chain3_andx_state);
92 NTSTATUS status;
94 status = cli_openx_recv(subreq, &state->fnum);
95 printf("cli_openx returned %s, fnum=%u\n", nt_errstr(status),
96 (unsigned)state->fnum);
97 TALLOC_FREE(subreq);
98 if (tevent_req_nterror(req, status)) {
99 return;
103 static void chain3_andx_write_done(struct tevent_req *subreq)
105 struct tevent_req *req = tevent_req_callback_data(
106 subreq, struct tevent_req);
107 struct chain3_andx_state *state = tevent_req_data(
108 req, struct chain3_andx_state);
109 NTSTATUS status;
111 status = cli_write_andx_recv(subreq, &state->written);
112 printf("cli_write_andx returned %s, written=%u\n", nt_errstr(status),
113 (unsigned)state->written);
114 TALLOC_FREE(subreq);
115 if (tevent_req_nterror(req, status)) {
116 return;
120 static void chain3_andx_close_done(struct tevent_req *subreq)
122 struct tevent_req *req = tevent_req_callback_data(
123 subreq, struct tevent_req);
124 NTSTATUS status;
126 status = cli_close_recv(subreq);
127 printf("cli_close returned %s\n", nt_errstr(status));
128 TALLOC_FREE(subreq);
129 if (tevent_req_nterror(req, status)) {
130 return;
132 tevent_req_done(req);
135 static NTSTATUS chain3_andx_recv(struct tevent_req *req)
137 return tevent_req_simple_recv_ntstatus(req);
140 struct chain3_state {
141 struct tevent_context *ev;
142 struct cli_state *cli;
143 const char *fname;
144 uint16_t fnum;
147 static void chain3_got_break(struct tevent_req *subreq);
148 static void chain3_ntcreate_done(struct tevent_req *subreq);
149 static void chain3_break_close_done(struct tevent_req *subreq);
150 static void chain3_andx_done(struct tevent_req *subreq);
152 static struct tevent_req *chain3_send(TALLOC_CTX *mem_ctx,
153 struct tevent_context *ev)
155 struct tevent_req *req, *subreq;
156 struct chain3_state *state;
158 req = tevent_req_create(mem_ctx, &state, struct chain3_state);
159 if (req == NULL) {
160 return NULL;
162 state->ev = ev;
163 state->fname = "chain3.txt";
165 if (!torture_open_connection(&state->cli, 0)) {
166 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
167 return tevent_req_post(req, ev);
170 subreq = cli_smb_oplock_break_waiter_send(
171 state, state->ev, state->cli);
172 if (tevent_req_nomem(subreq, req)) {
173 return tevent_req_post(req, ev);
175 tevent_req_set_callback(subreq, chain3_got_break, req);
177 subreq = cli_ntcreate_send(
178 state, state->ev, state->cli, state->fname,
179 REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK,
180 GENERIC_READ_ACCESS|GENERIC_WRITE_ACCESS,
181 FILE_ATTRIBUTE_NORMAL,
182 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
183 FILE_OVERWRITE_IF, 0,
184 SMB2_IMPERSONATION_IMPERSONATION, 0);
185 if (tevent_req_nomem(subreq, req)) {
186 return tevent_req_post(req, ev);
188 tevent_req_set_callback(subreq, chain3_ntcreate_done, req);
189 return req;
192 static void chain3_got_break(struct tevent_req *subreq)
194 struct tevent_req *req = tevent_req_callback_data(
195 subreq, struct tevent_req);
196 struct chain3_state *state = tevent_req_data(
197 req, struct chain3_state);
198 uint16_t fnum;
199 uint8_t level;
200 NTSTATUS status;
202 status = cli_smb_oplock_break_waiter_recv(subreq, &fnum, &level);
203 TALLOC_FREE(subreq);
204 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
205 nt_errstr(status));
206 if (tevent_req_nterror(req, status)) {
207 return;
209 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
210 if (tevent_req_nomem(subreq, req)) {
211 return;
213 tevent_req_set_callback(subreq, chain3_break_close_done, req);
216 static void chain3_break_close_done(struct tevent_req *subreq)
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 NTSTATUS status;
222 status = cli_close_recv(subreq);
223 TALLOC_FREE(subreq);
224 printf("cli_close_recv returned %s\n", nt_errstr(status));
225 if (tevent_req_nterror(req, status)) {
226 return;
230 static void chain3_ntcreate_done(struct tevent_req *subreq)
232 struct tevent_req *req = tevent_req_callback_data(
233 subreq, struct tevent_req);
234 struct chain3_state *state = tevent_req_data(
235 req, struct chain3_state);
236 NTSTATUS status;
238 status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
239 TALLOC_FREE(subreq);
240 printf("cli_ntcreate returned %s, fnum=%u\n", nt_errstr(status),
241 (unsigned)state->fnum);
242 if (tevent_req_nterror(req, status)) {
243 return;
246 subreq = chain3_andx_send(state, state->ev, state->cli, state->fname);
247 if (tevent_req_nomem(subreq, req)) {
248 return;
250 tevent_req_set_callback(subreq, chain3_andx_done, req);
253 static void chain3_andx_done(struct tevent_req *subreq)
255 struct tevent_req *req = tevent_req_callback_data(
256 subreq, struct tevent_req);
257 NTSTATUS status;
259 status = chain3_andx_recv(subreq);
260 TALLOC_FREE(subreq);
261 printf("chain3_andx_recv returned %s\n", nt_errstr(status));
262 if (tevent_req_nterror(req, status)) {
263 return;
265 tevent_req_done(req);
268 static NTSTATUS chain3_recv(struct tevent_req *req)
270 return tevent_req_simple_recv_ntstatus(req);
273 bool run_chain3(int dummy)
275 TALLOC_CTX *frame = talloc_stackframe();
276 struct tevent_context *ev;
277 struct tevent_req *req;
278 NTSTATUS status = NT_STATUS_NO_MEMORY;
280 ev = samba_tevent_context_init(frame);
281 if (ev == NULL) {
282 goto fail;
284 req = chain3_send(frame, ev);
285 if (req == NULL) {
286 goto fail;
288 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
289 goto fail;
291 status = chain3_recv(req);
292 fail:
293 TALLOC_FREE(frame);
294 printf("run_chain3 returns %s\n", nt_errstr(status));
295 return NT_STATUS_IS_OK(status);