Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Test smbd chain routines
4 :
5 : Copyright (C) Volker Lendecke 2012
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
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"
29 :
30 : struct chain3_andx_state {
31 : uint16_t fnum;
32 : size_t written;
33 : char str[6];
34 : };
35 :
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);
39 :
40 5 : 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)
44 : {
45 0 : struct tevent_req *req, *subreq;
46 0 : struct tevent_req *smbreqs[3];
47 0 : struct chain3_andx_state *state;
48 0 : NTSTATUS status;
49 :
50 5 : req = tevent_req_create(mem_ctx, &state, struct chain3_andx_state);
51 5 : if (req == NULL) {
52 0 : return NULL;
53 : }
54 :
55 5 : strlcpy(state->str, "hello", sizeof(state->str));
56 :
57 5 : subreq = cli_openx_create(state, ev, cli, fname,
58 : O_CREAT|O_RDWR, 0, &smbreqs[0]);
59 5 : if (tevent_req_nomem(subreq, req)) {
60 0 : return tevent_req_post(req, ev);
61 : }
62 5 : tevent_req_set_callback(subreq, chain3_andx_open_done, req);
63 :
64 5 : subreq = cli_write_andx_create(state, ev, cli, 0, 0,
65 5 : (const uint8_t *)state->str, 0,
66 5 : strlen(state->str)+1,
67 : smbreqs, 1, &smbreqs[1]);
68 5 : if (tevent_req_nomem(subreq, req)) {
69 0 : return tevent_req_post(req, ev);
70 : }
71 5 : tevent_req_set_callback(subreq, chain3_andx_write_done, req);
72 :
73 5 : subreq = cli_smb1_close_create(state, ev, cli, 0, &smbreqs[2]);
74 5 : if (tevent_req_nomem(subreq, req)) {
75 0 : return tevent_req_post(req, ev);
76 : }
77 5 : tevent_req_set_callback(subreq, chain3_andx_close_done, req);
78 :
79 5 : status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
80 5 : if (tevent_req_nterror(req, status)) {
81 0 : return tevent_req_post(req, ev);
82 : }
83 5 : return req;
84 : }
85 :
86 5 : static void chain3_andx_open_done(struct tevent_req *subreq)
87 : {
88 5 : struct tevent_req *req = tevent_req_callback_data(
89 : subreq, struct tevent_req);
90 5 : struct chain3_andx_state *state = tevent_req_data(
91 : req, struct chain3_andx_state);
92 0 : NTSTATUS status;
93 :
94 5 : status = cli_openx_recv(subreq, &state->fnum);
95 5 : printf("cli_openx returned %s, fnum=%u\n", nt_errstr(status),
96 5 : (unsigned)state->fnum);
97 5 : TALLOC_FREE(subreq);
98 5 : if (tevent_req_nterror(req, status)) {
99 0 : return;
100 : }
101 : }
102 :
103 5 : static void chain3_andx_write_done(struct tevent_req *subreq)
104 : {
105 5 : struct tevent_req *req = tevent_req_callback_data(
106 : subreq, struct tevent_req);
107 5 : struct chain3_andx_state *state = tevent_req_data(
108 : req, struct chain3_andx_state);
109 0 : NTSTATUS status;
110 :
111 5 : status = cli_write_andx_recv(subreq, &state->written);
112 5 : printf("cli_write_andx returned %s, written=%u\n", nt_errstr(status),
113 5 : (unsigned)state->written);
114 5 : TALLOC_FREE(subreq);
115 5 : if (tevent_req_nterror(req, status)) {
116 0 : return;
117 : }
118 : }
119 :
120 5 : static void chain3_andx_close_done(struct tevent_req *subreq)
121 : {
122 5 : struct tevent_req *req = tevent_req_callback_data(
123 : subreq, struct tevent_req);
124 0 : NTSTATUS status;
125 :
126 5 : status = cli_close_recv(subreq);
127 5 : printf("cli_close returned %s\n", nt_errstr(status));
128 5 : TALLOC_FREE(subreq);
129 5 : if (tevent_req_nterror(req, status)) {
130 0 : return;
131 : }
132 5 : tevent_req_done(req);
133 : }
134 :
135 5 : static NTSTATUS chain3_andx_recv(struct tevent_req *req)
136 : {
137 5 : return tevent_req_simple_recv_ntstatus(req);
138 : }
139 :
140 : struct chain3_state {
141 : struct tevent_context *ev;
142 : struct cli_state *cli;
143 : const char *fname;
144 : uint16_t fnum;
145 : };
146 :
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);
151 :
152 5 : static struct tevent_req *chain3_send(TALLOC_CTX *mem_ctx,
153 : struct tevent_context *ev)
154 : {
155 0 : struct tevent_req *req, *subreq;
156 0 : struct chain3_state *state;
157 :
158 5 : req = tevent_req_create(mem_ctx, &state, struct chain3_state);
159 5 : if (req == NULL) {
160 0 : return NULL;
161 : }
162 5 : state->ev = ev;
163 5 : state->fname = "chain3.txt";
164 :
165 5 : if (!torture_open_connection(&state->cli, 0)) {
166 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
167 0 : return tevent_req_post(req, ev);
168 : }
169 :
170 5 : subreq = cli_smb_oplock_break_waiter_send(
171 5 : state, state->ev, state->cli);
172 5 : if (tevent_req_nomem(subreq, req)) {
173 0 : return tevent_req_post(req, ev);
174 : }
175 5 : tevent_req_set_callback(subreq, chain3_got_break, req);
176 :
177 5 : subreq = cli_ntcreate_send(
178 5 : 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 5 : if (tevent_req_nomem(subreq, req)) {
186 0 : return tevent_req_post(req, ev);
187 : }
188 5 : tevent_req_set_callback(subreq, chain3_ntcreate_done, req);
189 5 : return req;
190 : }
191 :
192 5 : static void chain3_got_break(struct tevent_req *subreq)
193 : {
194 5 : struct tevent_req *req = tevent_req_callback_data(
195 : subreq, struct tevent_req);
196 5 : struct chain3_state *state = tevent_req_data(
197 : req, struct chain3_state);
198 0 : uint16_t fnum;
199 0 : uint8_t level;
200 0 : NTSTATUS status;
201 :
202 5 : status = cli_smb_oplock_break_waiter_recv(subreq, &fnum, &level);
203 5 : TALLOC_FREE(subreq);
204 5 : printf("cli_smb_oplock_break_waiter_recv returned %s\n",
205 : nt_errstr(status));
206 5 : if (tevent_req_nterror(req, status)) {
207 0 : return;
208 : }
209 5 : subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
210 5 : if (tevent_req_nomem(subreq, req)) {
211 0 : return;
212 : }
213 5 : tevent_req_set_callback(subreq, chain3_break_close_done, req);
214 : }
215 :
216 5 : static void chain3_break_close_done(struct tevent_req *subreq)
217 : {
218 5 : struct tevent_req *req = tevent_req_callback_data(
219 : subreq, struct tevent_req);
220 0 : NTSTATUS status;
221 :
222 5 : status = cli_close_recv(subreq);
223 5 : TALLOC_FREE(subreq);
224 5 : printf("cli_close_recv returned %s\n", nt_errstr(status));
225 5 : if (tevent_req_nterror(req, status)) {
226 0 : return;
227 : }
228 : }
229 :
230 5 : static void chain3_ntcreate_done(struct tevent_req *subreq)
231 : {
232 5 : struct tevent_req *req = tevent_req_callback_data(
233 : subreq, struct tevent_req);
234 5 : struct chain3_state *state = tevent_req_data(
235 : req, struct chain3_state);
236 0 : NTSTATUS status;
237 :
238 5 : status = cli_ntcreate_recv(subreq, &state->fnum, NULL);
239 5 : TALLOC_FREE(subreq);
240 5 : printf("cli_ntcreate returned %s, fnum=%u\n", nt_errstr(status),
241 5 : (unsigned)state->fnum);
242 5 : if (tevent_req_nterror(req, status)) {
243 0 : return;
244 : }
245 :
246 5 : subreq = chain3_andx_send(state, state->ev, state->cli, state->fname);
247 5 : if (tevent_req_nomem(subreq, req)) {
248 0 : return;
249 : }
250 5 : tevent_req_set_callback(subreq, chain3_andx_done, req);
251 : }
252 :
253 5 : static void chain3_andx_done(struct tevent_req *subreq)
254 : {
255 5 : struct tevent_req *req = tevent_req_callback_data(
256 : subreq, struct tevent_req);
257 0 : NTSTATUS status;
258 :
259 5 : status = chain3_andx_recv(subreq);
260 5 : TALLOC_FREE(subreq);
261 5 : printf("chain3_andx_recv returned %s\n", nt_errstr(status));
262 5 : if (tevent_req_nterror(req, status)) {
263 0 : return;
264 : }
265 5 : tevent_req_done(req);
266 : }
267 :
268 5 : static NTSTATUS chain3_recv(struct tevent_req *req)
269 : {
270 5 : return tevent_req_simple_recv_ntstatus(req);
271 : }
272 :
273 5 : bool run_chain3(int dummy)
274 : {
275 5 : TALLOC_CTX *frame = talloc_stackframe();
276 0 : struct tevent_context *ev;
277 0 : struct tevent_req *req;
278 5 : NTSTATUS status = NT_STATUS_NO_MEMORY;
279 :
280 5 : ev = samba_tevent_context_init(frame);
281 5 : if (ev == NULL) {
282 0 : goto fail;
283 : }
284 5 : req = chain3_send(frame, ev);
285 5 : if (req == NULL) {
286 0 : goto fail;
287 : }
288 5 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
289 0 : goto fail;
290 : }
291 5 : status = chain3_recv(req);
292 5 : fail:
293 5 : TALLOC_FREE(frame);
294 5 : printf("run_chain3 returns %s\n", nt_errstr(status));
295 5 : return NT_STATUS_IS_OK(status);
296 : }
|