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