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 331861 : bool fsp_is_np(struct files_struct *fsp)
39 : {
40 7645 : enum FAKE_FILE_TYPE type;
41 :
42 331861 : if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
43 0 : return false;
44 : }
45 :
46 331861 : type = fsp->fake_file_handle->type;
47 :
48 331861 : return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
49 : }
50 :
51 16987 : 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 16987 : struct npa_state *npa = NULL;
62 620 : int ret;
63 :
64 16987 : handle = talloc(mem_ctx, struct fake_file_handle);
65 16987 : if (handle == NULL) {
66 0 : return NT_STATUS_NO_MEMORY;
67 : }
68 :
69 16987 : npa = npa_state_init(handle);
70 16987 : if (npa == NULL) {
71 0 : TALLOC_FREE(handle);
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 16987 : *handle = (struct fake_file_handle) {
75 : .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
76 : .private_data = npa,
77 : };
78 :
79 16987 : 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 16987 : 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 16836 : *phandle = handle;
98 :
99 16836 : return NT_STATUS_OK;
100 : }
101 :
102 1414 : bool np_read_in_progress(struct fake_file_handle *handle)
103 : {
104 1414 : if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
105 0 : struct npa_state *p =
106 1414 : talloc_get_type_abort(handle->private_data,
107 : struct npa_state);
108 0 : size_t read_count;
109 :
110 1414 : read_count = tevent_queue_length(p->read_queue);
111 1414 : if (read_count > 0) {
112 0 : return true;
113 : }
114 :
115 1414 : 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 322949 : 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 7598 : struct tevent_req *req;
135 7598 : struct np_write_state *state;
136 322949 : struct npa_state *p = NULL;
137 322949 : struct tevent_req *subreq = NULL;
138 :
139 322949 : DBG_INFO("len: %zu\n", len);
140 322949 : dump_data(50, data, len);
141 :
142 322949 : req = tevent_req_create(mem_ctx, &state, struct np_write_state);
143 322949 : if (req == NULL) {
144 0 : return NULL;
145 : }
146 :
147 322949 : 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 322949 : 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 322949 : p = talloc_get_type_abort(handle->private_data, struct npa_state);
159 :
160 322949 : state->ev = ev;
161 322949 : state->p = p;
162 322949 : state->iov.iov_base = discard_const_p(void, data);
163 322949 : state->iov.iov_len = len;
164 :
165 330547 : subreq = tstream_writev_queue_send(
166 322949 : state, ev, p->stream, p->write_queue, &state->iov, 1);
167 322949 : if (tevent_req_nomem(subreq, req)) {
168 0 : return tevent_req_post(req, ev);
169 : }
170 322949 : tevent_req_set_callback(subreq, np_write_done, req);
171 322949 : return req;
172 : }
173 :
174 322949 : static void np_write_done(struct tevent_req *subreq)
175 : {
176 322949 : struct tevent_req *req = tevent_req_callback_data(
177 : subreq, struct tevent_req);
178 322949 : struct np_write_state *state = tevent_req_data(
179 : req, struct np_write_state);
180 7598 : ssize_t received;
181 7598 : int err;
182 :
183 322949 : received = tstream_writev_queue_recv(subreq, &err);
184 322949 : if (received < 0) {
185 0 : tevent_req_nterror(req, map_nt_error_from_unix(err));
186 0 : return;
187 : }
188 322949 : state->nwritten = received;
189 322949 : tevent_req_done(req);
190 : }
191 :
192 322949 : NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
193 : {
194 322949 : struct np_write_state *state = tevent_req_data(
195 : req, struct np_write_state);
196 7598 : NTSTATUS status;
197 :
198 322949 : if (tevent_req_is_nterror(req, &status)) {
199 0 : return status;
200 : }
201 322949 : *pnwritten = state->nwritten;
202 322949 : 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 323292 : 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 330890 : ZERO_STRUCTP(s);
216 :
217 323292 : s->buf = buf;
218 323292 : s->len = MIN(len, UINT16_MAX);
219 315694 : }
220 :
221 969846 : 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 969846 : struct np_ipc_readv_next_vector_state *state =
228 : (struct np_ipc_readv_next_vector_state *)private_data;
229 22788 : struct iovec *vector;
230 22788 : ssize_t pending;
231 22788 : size_t wanted;
232 :
233 969846 : if (state->ofs == state->len) {
234 4034 : *_vector = NULL;
235 4034 : *count = 0;
236 4034 : return 0;
237 : }
238 :
239 965812 : pending = tstream_pending_bytes(stream);
240 965812 : if (pending == -1) {
241 0 : return -1;
242 : }
243 :
244 965812 : if (pending == 0 && state->ofs != 0) {
245 : /* return a short read */
246 319243 : *_vector = NULL;
247 319243 : *count = 0;
248 319243 : return 0;
249 : }
250 :
251 646569 : if (pending == 0) {
252 : /* we want at least one byte and recheck again */
253 315694 : wanted = 1;
254 : } else {
255 323277 : size_t missing = state->len - state->ofs;
256 323277 : 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 315682 : wanted = pending;
263 : }
264 : }
265 :
266 646569 : vector = talloc_array(mem_ctx, struct iovec, 1);
267 646569 : if (!vector) {
268 0 : return -1;
269 : }
270 :
271 646569 : vector[0].iov_base = state->buf + state->ofs;
272 646569 : vector[0].iov_len = wanted;
273 :
274 646569 : state->ofs += wanted;
275 :
276 646569 : *_vector = vector;
277 646569 : *count = 1;
278 646569 : 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 323292 : 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 7598 : struct tevent_req *req;
296 7598 : struct np_read_state *state;
297 323292 : struct npa_state *p = NULL;
298 323292 : struct tevent_req *subreq = NULL;
299 :
300 323292 : req = tevent_req_create(mem_ctx, &state, struct np_read_state);
301 323292 : if (req == NULL) {
302 0 : return NULL;
303 : }
304 :
305 323292 : 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 323292 : p = talloc_get_type_abort(handle->private_data, struct npa_state);
311 :
312 323292 : np_ipc_readv_next_vector_init(&state->next_vector, data, len);
313 :
314 330890 : subreq = tstream_readv_pdu_queue_send(
315 : state,
316 : ev,
317 : p->stream,
318 : p->read_queue,
319 : np_ipc_readv_next_vector,
320 323292 : &state->next_vector);
321 323292 : if (tevent_req_nomem(subreq, req)) {
322 0 : return tevent_req_post(req, ev);
323 : }
324 323292 : tevent_req_set_callback(subreq, np_read_done, req);
325 323292 : return req;
326 : }
327 :
328 323292 : static void np_read_done(struct tevent_req *subreq)
329 : {
330 323292 : struct tevent_req *req = tevent_req_callback_data(
331 : subreq, struct tevent_req);
332 323292 : struct np_read_state *state = tevent_req_data(
333 : req, struct np_read_state);
334 7598 : ssize_t ret;
335 7598 : int err;
336 :
337 323292 : ret = tstream_readv_pdu_queue_recv(subreq, &err);
338 323292 : TALLOC_FREE(subreq);
339 323292 : if (ret == -1) {
340 15 : tevent_req_nterror(req, map_nt_error_from_unix(err));
341 15 : return;
342 : }
343 :
344 323277 : state->nread = ret;
345 323277 : state->is_data_outstanding = (state->next_vector.remaining > 0);
346 :
347 323277 : tevent_req_done(req);
348 323277 : return;
349 : }
350 :
351 323292 : NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
352 : bool *is_data_outstanding)
353 : {
354 323292 : struct np_read_state *state = tevent_req_data(
355 : req, struct np_read_state);
356 7598 : NTSTATUS status;
357 :
358 323292 : if (tevent_req_is_nterror(req, &status)) {
359 15 : return status;
360 : }
361 :
362 323277 : DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
363 : (int)state->nread, state->is_data_outstanding?"":"no "));
364 :
365 323277 : *nread = state->nread;
366 323277 : *is_data_outstanding = state->is_data_outstanding;
367 323277 : return NT_STATUS_OK;
368 : }
|