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