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