Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : * Copyright (C) Andrew Tridgell 1992-1998,
5 : * Largely re-written : 2005
6 : * Copyright (C) Jeremy Allison 1998 - 2005
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 3 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "fake_file.h"
24 : #include "rpc_dce.h"
25 : #include "ntdomain.h"
26 : #include "rpc_server/rpc_ncacn_np.h"
27 : #include "rpc_server/srv_pipe_hnd.h"
28 : #include "rpc_client/local_np.h"
29 : #include "rpc_server/rpc_server.h"
30 : #include "rpc_server/rpc_config.h"
31 : #include "../lib/tsocket/tsocket.h"
32 : #include "../lib/util/tevent_ntstatus.h"
33 : #include "librpc/ndr/ndr_table.h"
34 :
35 : #undef DBGC_CLASS
36 : #define DBGC_CLASS DBGC_RPC_SRV
37 :
38 334926 : bool fsp_is_np(struct files_struct *fsp)
39 : {
40 7118 : enum FAKE_FILE_TYPE type;
41 :
42 334926 : if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
43 0 : return false;
44 : }
45 :
46 334926 : type = fsp->fake_file_handle->type;
47 :
48 334926 : return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
49 : }
50 :
51 17050 : NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
52 : const struct tsocket_address *remote_client_address,
53 : const struct tsocket_address *local_server_address,
54 : struct auth_session_info *session_info,
55 : struct tevent_context *ev_ctx,
56 : struct messaging_context *msg_ctx,
57 : struct dcesrv_context *dce_ctx,
58 : struct fake_file_handle **phandle)
59 : {
60 620 : struct fake_file_handle *handle;
61 17050 : struct npa_state *npa = NULL;
62 620 : int ret;
63 :
64 17050 : handle = talloc(mem_ctx, struct fake_file_handle);
65 17050 : if (handle == NULL) {
66 0 : return NT_STATUS_NO_MEMORY;
67 : }
68 :
69 17050 : npa = npa_state_init(handle);
70 17050 : if (npa == NULL) {
71 0 : TALLOC_FREE(handle);
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 17050 : *handle = (struct fake_file_handle) {
75 : .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
76 : .private_data = npa,
77 : };
78 :
79 17050 : ret = local_np_connect(
80 : name,
81 : NCACN_NP,
82 : NULL,
83 : remote_client_address,
84 : NULL,
85 : local_server_address,
86 : session_info,
87 : false,
88 : npa,
89 : &npa->stream);
90 17050 : if (ret != 0) {
91 151 : DBG_DEBUG("local_np_connect failed: %s\n",
92 : strerror(ret));
93 151 : TALLOC_FREE(handle);
94 151 : return map_nt_error_from_unix(ret);
95 : }
96 :
97 16899 : *phandle = handle;
98 :
99 16899 : return NT_STATUS_OK;
100 : }
101 :
102 1418 : bool np_read_in_progress(struct fake_file_handle *handle)
103 : {
104 1418 : if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
105 0 : struct npa_state *p =
106 1418 : talloc_get_type_abort(handle->private_data,
107 : struct npa_state);
108 0 : size_t read_count;
109 :
110 1418 : read_count = tevent_queue_length(p->read_queue);
111 1418 : if (read_count > 0) {
112 0 : return true;
113 : }
114 :
115 1418 : return false;
116 : }
117 :
118 0 : return false;
119 : }
120 :
121 : struct np_write_state {
122 : struct tevent_context *ev;
123 : struct npa_state *p;
124 : struct iovec iov;
125 : ssize_t nwritten;
126 : };
127 :
128 : static void np_write_done(struct tevent_req *subreq);
129 :
130 325984 : struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
131 : struct fake_file_handle *handle,
132 : const uint8_t *data, size_t len)
133 : {
134 7070 : struct tevent_req *req;
135 7070 : struct np_write_state *state;
136 325984 : struct npa_state *p = NULL;
137 325984 : struct tevent_req *subreq = NULL;
138 :
139 325984 : DBG_INFO("len: %zu\n", len);
140 325984 : dump_data(50, data, len);
141 :
142 325984 : req = tevent_req_create(mem_ctx, &state, struct np_write_state);
143 325984 : if (req == NULL) {
144 0 : return NULL;
145 : }
146 :
147 325984 : if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
148 0 : tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
149 0 : return tevent_req_post(req, ev);
150 : }
151 :
152 325984 : if (len == 0) {
153 0 : state->nwritten = 0;
154 0 : tevent_req_done(req);
155 0 : return tevent_req_post(req, ev);
156 : }
157 :
158 325984 : p = talloc_get_type_abort(handle->private_data, struct npa_state);
159 :
160 325984 : state->ev = ev;
161 325984 : state->p = p;
162 325984 : state->iov.iov_base = discard_const_p(void, data);
163 325984 : state->iov.iov_len = len;
164 :
165 333054 : subreq = tstream_writev_queue_send(
166 325984 : state, ev, p->stream, p->write_queue, &state->iov, 1);
167 325984 : if (tevent_req_nomem(subreq, req)) {
168 0 : return tevent_req_post(req, ev);
169 : }
170 325984 : tevent_req_set_callback(subreq, np_write_done, req);
171 325984 : return req;
172 : }
173 :
174 325984 : static void np_write_done(struct tevent_req *subreq)
175 : {
176 325984 : struct tevent_req *req = tevent_req_callback_data(
177 : subreq, struct tevent_req);
178 325984 : struct np_write_state *state = tevent_req_data(
179 : req, struct np_write_state);
180 7070 : ssize_t received;
181 7070 : int err;
182 :
183 325984 : received = tstream_writev_queue_recv(subreq, &err);
184 325984 : if (received < 0) {
185 0 : tevent_req_nterror(req, map_nt_error_from_unix(err));
186 0 : return;
187 : }
188 325984 : state->nwritten = received;
189 325984 : tevent_req_done(req);
190 : }
191 :
192 325984 : NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
193 : {
194 325984 : struct np_write_state *state = tevent_req_data(
195 : req, struct np_write_state);
196 7070 : NTSTATUS status;
197 :
198 325984 : if (tevent_req_is_nterror(req, &status)) {
199 0 : return status;
200 : }
201 325984 : *pnwritten = state->nwritten;
202 325984 : return NT_STATUS_OK;
203 : }
204 :
205 : struct np_ipc_readv_next_vector_state {
206 : uint8_t *buf;
207 : size_t len;
208 : off_t ofs;
209 : size_t remaining;
210 : };
211 :
212 326333 : static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
213 : uint8_t *buf, size_t len)
214 : {
215 333403 : ZERO_STRUCTP(s);
216 :
217 326333 : s->buf = buf;
218 326333 : s->len = MIN(len, UINT16_MAX);
219 319263 : }
220 :
221 978969 : static int np_ipc_readv_next_vector(struct tstream_context *stream,
222 : void *private_data,
223 : TALLOC_CTX *mem_ctx,
224 : struct iovec **_vector,
225 : size_t *count)
226 : {
227 978969 : struct np_ipc_readv_next_vector_state *state =
228 : (struct np_ipc_readv_next_vector_state *)private_data;
229 21204 : struct iovec *vector;
230 21204 : ssize_t pending;
231 21204 : size_t wanted;
232 :
233 978969 : if (state->ofs == state->len) {
234 4055 : *_vector = NULL;
235 4055 : *count = 0;
236 4055 : return 0;
237 : }
238 :
239 974914 : pending = tstream_pending_bytes(stream);
240 974914 : if (pending == -1) {
241 0 : return -1;
242 : }
243 :
244 974914 : if (pending == 0 && state->ofs != 0) {
245 : /* return a short read */
246 322263 : *_vector = NULL;
247 322263 : *count = 0;
248 322263 : return 0;
249 : }
250 :
251 652651 : if (pending == 0) {
252 : /* we want at least one byte and recheck again */
253 319263 : wanted = 1;
254 : } else {
255 326318 : size_t missing = state->len - state->ofs;
256 326318 : if (pending > missing) {
257 : /* there's more available */
258 0 : state->remaining = pending - missing;
259 0 : wanted = missing;
260 : } else {
261 : /* read what we can get and recheck in the next cycle */
262 319251 : wanted = pending;
263 : }
264 : }
265 :
266 652651 : vector = talloc_array(mem_ctx, struct iovec, 1);
267 652651 : if (!vector) {
268 0 : return -1;
269 : }
270 :
271 652651 : vector[0].iov_base = state->buf + state->ofs;
272 652651 : vector[0].iov_len = wanted;
273 :
274 652651 : state->ofs += wanted;
275 :
276 652651 : *_vector = vector;
277 652651 : *count = 1;
278 652651 : return 0;
279 : }
280 :
281 : struct np_read_state {
282 : struct npa_state *p;
283 : struct np_ipc_readv_next_vector_state next_vector;
284 :
285 : ssize_t nread;
286 : bool is_data_outstanding;
287 : };
288 :
289 : static void np_read_done(struct tevent_req *subreq);
290 :
291 326333 : struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
292 : struct fake_file_handle *handle,
293 : uint8_t *data, size_t len)
294 : {
295 7070 : struct tevent_req *req;
296 7070 : struct np_read_state *state;
297 326333 : struct npa_state *p = NULL;
298 326333 : struct tevent_req *subreq = NULL;
299 :
300 326333 : req = tevent_req_create(mem_ctx, &state, struct np_read_state);
301 326333 : if (req == NULL) {
302 0 : return NULL;
303 : }
304 :
305 326333 : if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
306 0 : tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
307 0 : return tevent_req_post(req, ev);
308 : }
309 :
310 326333 : p = talloc_get_type_abort(handle->private_data, struct npa_state);
311 :
312 326333 : np_ipc_readv_next_vector_init(&state->next_vector, data, len);
313 :
314 333403 : subreq = tstream_readv_pdu_queue_send(
315 : state,
316 : ev,
317 : p->stream,
318 : p->read_queue,
319 : np_ipc_readv_next_vector,
320 326333 : &state->next_vector);
321 326333 : if (tevent_req_nomem(subreq, req)) {
322 0 : return tevent_req_post(req, ev);
323 : }
324 326333 : tevent_req_set_callback(subreq, np_read_done, req);
325 326333 : return req;
326 : }
327 :
328 326333 : static void np_read_done(struct tevent_req *subreq)
329 : {
330 326333 : struct tevent_req *req = tevent_req_callback_data(
331 : subreq, struct tevent_req);
332 326333 : struct np_read_state *state = tevent_req_data(
333 : req, struct np_read_state);
334 7070 : ssize_t ret;
335 7070 : int err;
336 :
337 326333 : ret = tstream_readv_pdu_queue_recv(subreq, &err);
338 326333 : TALLOC_FREE(subreq);
339 326333 : if (ret == -1) {
340 15 : tevent_req_nterror(req, map_nt_error_from_unix(err));
341 15 : return;
342 : }
343 :
344 326318 : state->nread = ret;
345 326318 : state->is_data_outstanding = (state->next_vector.remaining > 0);
346 :
347 326318 : tevent_req_done(req);
348 326318 : return;
349 : }
350 :
351 326333 : NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
352 : bool *is_data_outstanding)
353 : {
354 326333 : struct np_read_state *state = tevent_req_data(
355 : req, struct np_read_state);
356 7070 : NTSTATUS status;
357 :
358 326333 : if (tevent_req_is_nterror(req, &status)) {
359 15 : return status;
360 : }
361 :
362 326318 : DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
363 : (int)state->nread, state->is_data_outstanding?"":"no "));
364 :
365 326318 : *nread = state->nread;
366 326318 : *is_data_outstanding = state->is_data_outstanding;
367 326318 : return NT_STATUS_OK;
368 : }
|