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/>.
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
{
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
,
45 struct tevent_req
*req
, *subreq
;
46 struct tevent_req
*smbreqs
[3];
47 struct chain3_andx_state
*state
;
50 req
= tevent_req_create(mem_ctx
, &state
, struct chain3_andx_state
);
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,
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
);
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
);
94 status
= cli_openx_recv(subreq
, &state
->fnum
);
95 printf("cli_openx returned %s, fnum=%u\n", nt_errstr(status
),
96 (unsigned)state
->fnum
);
98 if (tevent_req_nterror(req
, status
)) {
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
);
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
);
115 if (tevent_req_nterror(req
, status
)) {
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
);
126 status
= cli_close_recv(subreq
);
127 printf("cli_close returned %s\n", nt_errstr(status
));
129 if (tevent_req_nterror(req
, status
)) {
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
;
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
);
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
);
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
);
202 status
= cli_smb_oplock_break_waiter_recv(subreq
, &fnum
, &level
);
204 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
206 if (tevent_req_nterror(req
, status
)) {
209 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
);
210 if (tevent_req_nomem(subreq
, req
)) {
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
);
222 status
= cli_close_recv(subreq
);
224 printf("cli_close_recv returned %s\n", nt_errstr(status
));
225 if (tevent_req_nterror(req
, status
)) {
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
);
238 status
= cli_ntcreate_recv(subreq
, &state
->fnum
, NULL
);
240 printf("cli_ntcreate returned %s, fnum=%u\n", nt_errstr(status
),
241 (unsigned)state
->fnum
);
242 if (tevent_req_nterror(req
, status
)) {
246 subreq
= chain3_andx_send(state
, state
->ev
, state
->cli
, state
->fname
);
247 if (tevent_req_nomem(subreq
, req
)) {
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
);
259 status
= chain3_andx_recv(subreq
);
261 printf("chain3_andx_recv returned %s\n", nt_errstr(status
));
262 if (tevent_req_nterror(req
, status
)) {
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
);
284 req
= chain3_send(frame
, ev
);
288 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
291 status
= chain3_recv(req
);
294 printf("run_chain3 returns %s\n", nt_errstr(status
));
295 return NT_STATUS_IS_OK(status
);