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 89481 : bool fsp_is_np(struct files_struct *fsp)
39 : {
40 : enum FAKE_FILE_TYPE type;
41 :
42 89481 : if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
43 0 : return false;
44 : }
45 :
46 89481 : type = fsp->fake_file_handle->type;
47 :
48 89481 : return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
49 : }
50 :
51 3442 : 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 : struct fake_file_handle *handle;
61 3442 : struct npa_state *npa = NULL;
62 : int ret;
63 :
64 3442 : handle = talloc(mem_ctx, struct fake_file_handle);
65 3442 : if (handle == NULL) {
66 0 : return NT_STATUS_NO_MEMORY;
67 : }
68 :
69 3442 : npa = npa_state_init(handle);
70 3442 : if (npa == NULL) {
71 0 : TALLOC_FREE(handle);
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 3442 : *handle = (struct fake_file_handle) {
75 : .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
76 : .private_data = npa,
77 : };
78 :
79 3442 : 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 3442 : if (ret != 0) {
91 5 : DBG_DEBUG("local_np_connect failed: %s\n",
92 : strerror(ret));
93 5 : TALLOC_FREE(handle);
94 5 : return map_nt_error_from_unix(ret);
95 : }
96 :
97 3437 : *phandle = handle;
98 :
99 3437 : return NT_STATUS_OK;
100 : }
101 :
102 0 : bool np_read_in_progress(struct fake_file_handle *handle)
103 : {
104 0 : if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
105 0 : struct npa_state *p =
106 0 : talloc_get_type_abort(handle->private_data,
107 : struct npa_state);
108 : size_t read_count;
109 :
110 0 : read_count = tevent_queue_length(p->read_queue);
111 0 : if (read_count > 0) {
112 0 : return true;
113 : }
114 :
115 0 : 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 83472 : 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 : struct tevent_req *req;
135 : struct np_write_state *state;
136 : NTSTATUS status;
137 :
138 83472 : DBG_INFO("len: %zu\n", len);
139 83472 : dump_data(50, data, len);
140 :
141 83472 : req = tevent_req_create(mem_ctx, &state, struct np_write_state);
142 83472 : if (req == NULL) {
143 0 : return NULL;
144 : }
145 :
146 83472 : if (len == 0) {
147 0 : state->nwritten = 0;
148 0 : status = NT_STATUS_OK;
149 0 : goto post_status;
150 : }
151 :
152 83472 : if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
153 83472 : struct npa_state *p = talloc_get_type_abort(
154 : handle->private_data, struct npa_state);
155 : struct tevent_req *subreq;
156 :
157 83472 : state->ev = ev;
158 83472 : state->p = p;
159 83472 : state->iov.iov_base = discard_const_p(void, data);
160 83472 : state->iov.iov_len = len;
161 :
162 83472 : subreq = tstream_writev_queue_send(state, ev,
163 : p->stream,
164 : p->write_queue,
165 83472 : &state->iov, 1);
166 83472 : if (subreq == NULL) {
167 0 : goto fail;
168 : }
169 83472 : tevent_req_set_callback(subreq, np_write_done, req);
170 83472 : return req;
171 : }
172 :
173 0 : status = NT_STATUS_INVALID_HANDLE;
174 0 : post_status:
175 0 : if (NT_STATUS_IS_OK(status)) {
176 0 : tevent_req_done(req);
177 : } else {
178 0 : tevent_req_nterror(req, status);
179 : }
180 0 : return tevent_req_post(req, ev);
181 0 : fail:
182 0 : TALLOC_FREE(req);
183 0 : return NULL;
184 : }
185 :
186 83472 : static void np_write_done(struct tevent_req *subreq)
187 : {
188 83472 : struct tevent_req *req = tevent_req_callback_data(
189 : subreq, struct tevent_req);
190 83472 : struct np_write_state *state = tevent_req_data(
191 : req, struct np_write_state);
192 : ssize_t received;
193 : int err;
194 :
195 83472 : received = tstream_writev_queue_recv(subreq, &err);
196 83472 : if (received < 0) {
197 0 : tevent_req_nterror(req, map_nt_error_from_unix(err));
198 0 : return;
199 : }
200 83472 : state->nwritten = received;
201 83472 : tevent_req_done(req);
202 : }
203 :
204 83472 : NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
205 : {
206 83472 : struct np_write_state *state = tevent_req_data(
207 : req, struct np_write_state);
208 : NTSTATUS status;
209 :
210 83472 : if (tevent_req_is_nterror(req, &status)) {
211 0 : return status;
212 : }
213 83472 : *pnwritten = state->nwritten;
214 83472 : return NT_STATUS_OK;
215 : }
216 :
217 : struct np_ipc_readv_next_vector_state {
218 : uint8_t *buf;
219 : size_t len;
220 : off_t ofs;
221 : size_t remaining;
222 : };
223 :
224 83580 : static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
225 : uint8_t *buf, size_t len)
226 : {
227 83580 : ZERO_STRUCTP(s);
228 :
229 83580 : s->buf = buf;
230 83580 : s->len = MIN(len, UINT16_MAX);
231 83580 : }
232 :
233 250728 : static int np_ipc_readv_next_vector(struct tstream_context *stream,
234 : void *private_data,
235 : TALLOC_CTX *mem_ctx,
236 : struct iovec **_vector,
237 : size_t *count)
238 : {
239 250728 : struct np_ipc_readv_next_vector_state *state =
240 : (struct np_ipc_readv_next_vector_state *)private_data;
241 : struct iovec *vector;
242 : ssize_t pending;
243 : size_t wanted;
244 :
245 250728 : if (state->ofs == state->len) {
246 2978 : *_vector = NULL;
247 2978 : *count = 0;
248 2978 : return 0;
249 : }
250 :
251 247750 : pending = tstream_pending_bytes(stream);
252 247750 : if (pending == -1) {
253 0 : return -1;
254 : }
255 :
256 247750 : if (pending == 0 && state->ofs != 0) {
257 : /* return a short read */
258 80596 : *_vector = NULL;
259 80596 : *count = 0;
260 80596 : return 0;
261 : }
262 :
263 167154 : if (pending == 0) {
264 : /* we want at least one byte and recheck again */
265 83580 : wanted = 1;
266 : } else {
267 83574 : size_t missing = state->len - state->ofs;
268 83574 : if (pending > missing) {
269 : /* there's more available */
270 0 : state->remaining = pending - missing;
271 0 : wanted = missing;
272 : } else {
273 : /* read what we can get and recheck in the next cycle */
274 83574 : wanted = pending;
275 : }
276 : }
277 :
278 167154 : vector = talloc_array(mem_ctx, struct iovec, 1);
279 167154 : if (!vector) {
280 0 : return -1;
281 : }
282 :
283 167154 : vector[0].iov_base = state->buf + state->ofs;
284 167154 : vector[0].iov_len = wanted;
285 :
286 167154 : state->ofs += wanted;
287 :
288 167154 : *_vector = vector;
289 167154 : *count = 1;
290 167154 : return 0;
291 : }
292 :
293 : struct np_read_state {
294 : struct npa_state *p;
295 : struct np_ipc_readv_next_vector_state next_vector;
296 :
297 : ssize_t nread;
298 : bool is_data_outstanding;
299 : };
300 :
301 : static void np_read_done(struct tevent_req *subreq);
302 :
303 83580 : struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
304 : struct fake_file_handle *handle,
305 : uint8_t *data, size_t len)
306 : {
307 : struct tevent_req *req;
308 : struct np_read_state *state;
309 : NTSTATUS status;
310 :
311 83580 : req = tevent_req_create(mem_ctx, &state, struct np_read_state);
312 83580 : if (req == NULL) {
313 0 : return NULL;
314 : }
315 :
316 83580 : if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
317 83580 : struct npa_state *p = talloc_get_type_abort(
318 : handle->private_data, struct npa_state);
319 : struct tevent_req *subreq;
320 :
321 83580 : np_ipc_readv_next_vector_init(&state->next_vector,
322 : data, len);
323 :
324 83580 : subreq = tstream_readv_pdu_queue_send(state,
325 : ev,
326 : p->stream,
327 : p->read_queue,
328 : np_ipc_readv_next_vector,
329 83580 : &state->next_vector);
330 83580 : if (subreq == NULL) {
331 0 : status = NT_STATUS_NO_MEMORY;
332 0 : goto post_status;
333 : }
334 83580 : tevent_req_set_callback(subreq, np_read_done, req);
335 83580 : return req;
336 : }
337 :
338 0 : status = NT_STATUS_INVALID_HANDLE;
339 0 : post_status:
340 0 : if (NT_STATUS_IS_OK(status)) {
341 0 : tevent_req_done(req);
342 : } else {
343 0 : tevent_req_nterror(req, status);
344 : }
345 0 : return tevent_req_post(req, ev);
346 : }
347 :
348 83580 : static void np_read_done(struct tevent_req *subreq)
349 : {
350 83580 : struct tevent_req *req = tevent_req_callback_data(
351 : subreq, struct tevent_req);
352 83580 : struct np_read_state *state = tevent_req_data(
353 : req, struct np_read_state);
354 : ssize_t ret;
355 : int err;
356 :
357 83580 : ret = tstream_readv_pdu_queue_recv(subreq, &err);
358 83580 : TALLOC_FREE(subreq);
359 83580 : if (ret == -1) {
360 6 : tevent_req_nterror(req, map_nt_error_from_unix(err));
361 6 : return;
362 : }
363 :
364 83574 : state->nread = ret;
365 83574 : state->is_data_outstanding = (state->next_vector.remaining > 0);
366 :
367 83574 : tevent_req_done(req);
368 83574 : return;
369 : }
370 :
371 83580 : NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
372 : bool *is_data_outstanding)
373 : {
374 83580 : struct np_read_state *state = tevent_req_data(
375 : req, struct np_read_state);
376 : NTSTATUS status;
377 :
378 83580 : if (tevent_req_is_nterror(req, &status)) {
379 6 : return status;
380 : }
381 :
382 83574 : DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
383 : (int)state->nread, state->is_data_outstanding?"":"no "));
384 :
385 83574 : *nread = state->nread;
386 83574 : *is_data_outstanding = state->is_data_outstanding;
387 83574 : return NT_STATUS_OK;
388 : }
|