Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2009
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "system/network.h"
22 : #include "../util/tevent_unix.h"
23 : #include "../lib/tsocket/tsocket.h"
24 : #include "../lib/tsocket/tsocket_internal.h"
25 : #include "../librpc/gen_ndr/ndr_named_pipe_auth.h"
26 : #include "../libcli/named_pipe_auth/npa_tstream.h"
27 : #include "../libcli/named_pipe_auth/tstream_u32_read.h"
28 : #include "../libcli/smb/smb_constants.h"
29 :
30 : static const struct tstream_context_ops tstream_npa_ops;
31 :
32 : struct tstream_npa {
33 : struct tstream_context *unix_stream;
34 :
35 : uint16_t file_type;
36 :
37 : struct iovec pending;
38 : };
39 :
40 : struct tstream_npa_connect_state {
41 : struct {
42 : struct tevent_context *ev;
43 : } caller;
44 :
45 : const char *unix_path;
46 : struct tsocket_address *unix_laddr;
47 : struct tsocket_address *unix_raddr;
48 : struct tstream_context *unix_stream;
49 :
50 : struct named_pipe_auth_req auth_req;
51 : DATA_BLOB auth_req_blob;
52 : struct iovec auth_req_iov;
53 :
54 : struct named_pipe_auth_rep auth_rep;
55 : };
56 :
57 : static void tstream_npa_connect_unix_done(struct tevent_req *subreq);
58 :
59 1330 : struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
60 : struct tevent_context *ev,
61 : const char *directory,
62 : const char *npipe,
63 : enum dcerpc_transport_t transport,
64 : const struct tsocket_address *remote_client_addr,
65 : const char *remote_client_name_in,
66 : const struct tsocket_address *local_server_addr,
67 : const char *local_server_name_in,
68 : const struct auth_session_info_transport *session_info)
69 : {
70 0 : struct tevent_req *req;
71 0 : struct tstream_npa_connect_state *state;
72 0 : struct tevent_req *subreq;
73 0 : int ret;
74 0 : enum ndr_err_code ndr_err;
75 0 : char *lower_case_npipe;
76 0 : struct named_pipe_auth_req_info8 *info8;
77 :
78 1330 : req = tevent_req_create(mem_ctx, &state,
79 : struct tstream_npa_connect_state);
80 1330 : if (!req) {
81 0 : return NULL;
82 : }
83 :
84 1330 : state->caller.ev = ev;
85 :
86 1330 : lower_case_npipe = strlower_talloc(state, npipe);
87 1330 : if (tevent_req_nomem(lower_case_npipe, req)) {
88 0 : goto post;
89 : }
90 :
91 1330 : state->unix_path = talloc_asprintf(state, "%s/%s",
92 : directory,
93 : lower_case_npipe);
94 1330 : talloc_free(lower_case_npipe);
95 1330 : if (tevent_req_nomem(state->unix_path, req)) {
96 0 : goto post;
97 : }
98 :
99 1330 : ret = tsocket_address_unix_from_path(state,
100 : "",
101 : &state->unix_laddr);
102 1330 : if (ret == -1) {
103 0 : tevent_req_error(req, errno);
104 0 : goto post;
105 : }
106 :
107 1330 : ret = tsocket_address_unix_from_path(state,
108 : state->unix_path,
109 : &state->unix_raddr);
110 1330 : if (ret == -1) {
111 0 : tevent_req_error(req, errno);
112 0 : goto post;
113 : }
114 :
115 1330 : ZERO_STRUCT(state->auth_req);
116 :
117 1330 : if (!local_server_addr) {
118 0 : tevent_req_error(req, EINVAL);
119 0 : goto post;
120 : }
121 :
122 1330 : state->auth_req.level = 8;
123 1330 : info8 = &state->auth_req.info.info8;
124 :
125 1330 : info8->transport = transport;
126 1330 : SMB_ASSERT(info8->transport == transport); /* Assert no overflow */
127 :
128 1330 : info8->remote_client_name = remote_client_name_in;
129 1330 : info8->remote_client_addr =
130 1330 : tsocket_address_inet_addr_string(remote_client_addr, state);
131 1330 : if (!info8->remote_client_addr) {
132 : /* errno might be EINVAL */
133 0 : tevent_req_error(req, errno);
134 0 : goto post;
135 : }
136 1330 : info8->remote_client_port =
137 1330 : tsocket_address_inet_port(remote_client_addr);
138 1330 : if (!info8->remote_client_name) {
139 1330 : info8->remote_client_name = info8->remote_client_addr;
140 : }
141 :
142 1330 : info8->local_server_name = local_server_name_in;
143 1330 : info8->local_server_addr =
144 1330 : tsocket_address_inet_addr_string(local_server_addr, state);
145 1330 : if (!info8->local_server_addr) {
146 : /* errno might be EINVAL */
147 0 : tevent_req_error(req, errno);
148 0 : goto post;
149 : }
150 1330 : info8->local_server_port =
151 1330 : tsocket_address_inet_port(local_server_addr);
152 1330 : if (!info8->local_server_name) {
153 1330 : info8->local_server_name = info8->local_server_addr;
154 : }
155 :
156 1330 : info8->session_info =
157 : discard_const_p(struct auth_session_info_transport,
158 : session_info);
159 :
160 1330 : if (DEBUGLVL(10)) {
161 0 : NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
162 : }
163 :
164 1330 : ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
165 1330 : state, &state->auth_req,
166 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
167 1330 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
168 0 : tevent_req_error(req, EINVAL);
169 0 : goto post;
170 : }
171 :
172 1330 : state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
173 1330 : state->auth_req_iov.iov_len = state->auth_req_blob.length;
174 :
175 1330 : subreq = tstream_unix_connect_send(state,
176 1330 : state->caller.ev,
177 1330 : state->unix_laddr,
178 1330 : state->unix_raddr);
179 1330 : if (tevent_req_nomem(subreq, req)) {
180 0 : goto post;
181 : }
182 1330 : tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
183 :
184 1330 : return req;
185 :
186 0 : post:
187 0 : tevent_req_post(req, ev);
188 0 : return req;
189 : }
190 :
191 : static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
192 :
193 1330 : static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
194 : {
195 0 : struct tevent_req *req =
196 1330 : tevent_req_callback_data(subreq,
197 : struct tevent_req);
198 0 : struct tstream_npa_connect_state *state =
199 1330 : tevent_req_data(req,
200 : struct tstream_npa_connect_state);
201 0 : int ret;
202 0 : int sys_errno;
203 :
204 1330 : ret = tstream_unix_connect_recv(subreq, &sys_errno,
205 : state, &state->unix_stream);
206 1330 : TALLOC_FREE(subreq);
207 1330 : if (ret == -1) {
208 84 : tevent_req_error(req, sys_errno);
209 84 : return;
210 : }
211 :
212 1246 : subreq = tstream_writev_send(state,
213 : state->caller.ev,
214 : state->unix_stream,
215 1246 : &state->auth_req_iov, 1);
216 1246 : if (tevent_req_nomem(subreq, req)) {
217 0 : return;
218 : }
219 1246 : tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
220 : }
221 :
222 : static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
223 :
224 1246 : static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
225 : {
226 0 : struct tevent_req *req =
227 1246 : tevent_req_callback_data(subreq,
228 : struct tevent_req);
229 0 : struct tstream_npa_connect_state *state =
230 1246 : tevent_req_data(req,
231 : struct tstream_npa_connect_state);
232 0 : int ret;
233 0 : int sys_errno;
234 :
235 1246 : ret = tstream_writev_recv(subreq, &sys_errno);
236 1246 : TALLOC_FREE(subreq);
237 1246 : if (ret == -1) {
238 0 : tevent_req_error(req, sys_errno);
239 0 : return;
240 : }
241 :
242 1246 : subreq = tstream_u32_read_send(
243 : state, state->caller.ev, 0x00FFFFFF, state->unix_stream);
244 1246 : if (tevent_req_nomem(subreq, req)) {
245 0 : return;
246 : }
247 1246 : tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
248 : }
249 :
250 1246 : static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
251 : {
252 0 : struct tevent_req *req =
253 1246 : tevent_req_callback_data(subreq,
254 : struct tevent_req);
255 0 : struct tstream_npa_connect_state *state =
256 1246 : tevent_req_data(req,
257 : struct tstream_npa_connect_state);
258 0 : DATA_BLOB in;
259 0 : int err;
260 0 : enum ndr_err_code ndr_err;
261 :
262 1246 : err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
263 1246 : TALLOC_FREE(subreq);
264 1246 : if (tevent_req_error(req, err)) {
265 0 : return;
266 : }
267 :
268 1246 : DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in.length);
269 1246 : dump_data(11, in.data, in.length);
270 :
271 1246 : ndr_err = ndr_pull_struct_blob_all(
272 : &in,
273 : state,
274 1246 : &state->auth_rep,
275 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
276 :
277 1246 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
278 0 : DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
279 : ndr_map_error2string(ndr_err)));
280 0 : tevent_req_error(req, EIO);
281 0 : return;
282 : }
283 :
284 1246 : if (DEBUGLVL(10)) {
285 0 : NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
286 : }
287 :
288 1246 : if (state->auth_rep.length < 16) {
289 0 : DEBUG(0, ("req invalid length: %u < 16\n",
290 : state->auth_rep.length));
291 0 : tevent_req_error(req, EIO);
292 0 : return;
293 : }
294 :
295 1246 : if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
296 0 : DEBUG(0, ("req invalid magic: %s != %s\n",
297 : state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
298 0 : tevent_req_error(req, EIO);
299 0 : return;
300 : }
301 :
302 1246 : if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
303 0 : DEBUG(0, ("req failed: %s\n",
304 : nt_errstr(state->auth_rep.status)));
305 0 : tevent_req_error(req, EACCES);
306 0 : return;
307 : }
308 :
309 1246 : if (state->auth_rep.level != state->auth_req.level) {
310 0 : DEBUG(0, ("req invalid level: %u != %u\n",
311 : state->auth_rep.level, state->auth_req.level));
312 0 : tevent_req_error(req, EIO);
313 0 : return;
314 : }
315 :
316 1246 : tevent_req_done(req);
317 : }
318 :
319 1330 : int _tstream_npa_connect_recv(struct tevent_req *req,
320 : int *perrno,
321 : TALLOC_CTX *mem_ctx,
322 : struct tstream_context **_stream,
323 : uint16_t *_file_type,
324 : uint16_t *_device_state,
325 : uint64_t *_allocation_size,
326 : const char *location)
327 : {
328 0 : struct tstream_npa_connect_state *state =
329 1330 : tevent_req_data(req,
330 : struct tstream_npa_connect_state);
331 0 : struct tstream_context *stream;
332 0 : struct tstream_npa *npas;
333 1330 : uint16_t device_state = 0;
334 1330 : uint64_t allocation_size = 0;
335 :
336 1330 : if (tevent_req_is_unix_error(req, perrno)) {
337 84 : tevent_req_received(req);
338 84 : return -1;
339 : }
340 :
341 1246 : stream = tstream_context_create(mem_ctx,
342 : &tstream_npa_ops,
343 : &npas,
344 : struct tstream_npa,
345 : location);
346 1246 : if (!stream) {
347 0 : *perrno = ENOMEM;
348 0 : tevent_req_received(req);
349 0 : return -1;
350 : }
351 1246 : ZERO_STRUCTP(npas);
352 :
353 1246 : npas->unix_stream = talloc_move(stream, &state->unix_stream);
354 1246 : switch (state->auth_rep.level) {
355 1246 : case 8:
356 1246 : npas->file_type = state->auth_rep.info.info8.file_type;
357 1246 : device_state = state->auth_rep.info.info8.device_state;
358 1246 : allocation_size = state->auth_rep.info.info8.allocation_size;
359 1246 : break;
360 : }
361 :
362 1246 : *_stream = stream;
363 1246 : *_file_type = npas->file_type;
364 1246 : *_device_state = device_state;
365 1246 : *_allocation_size = allocation_size;
366 1246 : tevent_req_received(req);
367 1246 : return 0;
368 : }
369 :
370 1120609 : static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
371 : {
372 1120609 : struct tstream_npa *npas = tstream_context_data(stream,
373 : struct tstream_npa);
374 21156 : ssize_t ret;
375 :
376 1120609 : if (!npas->unix_stream) {
377 0 : errno = ENOTCONN;
378 0 : return -1;
379 : }
380 :
381 1120609 : switch (npas->file_type) {
382 0 : case FILE_TYPE_BYTE_MODE_PIPE:
383 0 : ret = tstream_pending_bytes(npas->unix_stream);
384 0 : break;
385 :
386 1120609 : case FILE_TYPE_MESSAGE_MODE_PIPE:
387 1120609 : ret = npas->pending.iov_len;
388 1120609 : break;
389 :
390 0 : default:
391 0 : ret = -1;
392 : }
393 :
394 1099453 : return ret;
395 : }
396 :
397 : struct tstream_npa_readv_state {
398 : struct tstream_context *stream;
399 :
400 : struct iovec *vector;
401 : size_t count;
402 :
403 : /* the header for message mode */
404 : uint8_t hdr[2];
405 : bool wait_for_hdr;
406 :
407 : int ret;
408 : };
409 :
410 : static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
411 : static int tstream_npa_readv_next_vector(struct tstream_context *stream,
412 : void *private_data,
413 : TALLOC_CTX *mem_ctx,
414 : struct iovec **_vector,
415 : size_t *_count);
416 : static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
417 :
418 3439150 : static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
419 : struct tevent_context *ev,
420 : struct tstream_context *stream,
421 : struct iovec *vector,
422 : size_t count)
423 : {
424 28979 : struct tevent_req *req;
425 28979 : struct tstream_npa_readv_state *state;
426 3439150 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
427 28979 : struct tevent_req *subreq;
428 28979 : off_t ofs;
429 28979 : size_t left;
430 28979 : uint8_t *pbase;
431 :
432 3439150 : req = tevent_req_create(mem_ctx, &state,
433 : struct tstream_npa_readv_state);
434 3439150 : if (!req) {
435 0 : return NULL;
436 : }
437 :
438 3439150 : state->stream = stream;
439 3439150 : state->ret = 0;
440 :
441 3439150 : if (!npas->unix_stream) {
442 0 : tevent_req_error(req, ENOTCONN);
443 0 : goto post;
444 : }
445 :
446 3439150 : switch (npas->file_type) {
447 0 : case FILE_TYPE_BYTE_MODE_PIPE:
448 0 : state->vector = vector;
449 0 : state->count = count;
450 :
451 0 : subreq = tstream_readv_send(state,
452 : ev,
453 : npas->unix_stream,
454 0 : state->vector,
455 0 : state->count);
456 0 : if (tevent_req_nomem(subreq,req)) {
457 0 : goto post;
458 : }
459 0 : tevent_req_set_callback(subreq,
460 : tstream_npa_readv_byte_mode_handler,
461 : req);
462 :
463 0 : return req;
464 :
465 3439150 : case FILE_TYPE_MESSAGE_MODE_PIPE:
466 : /*
467 : * we make a copy of the vector and prepend a header
468 : * with the length
469 : */
470 3439150 : state->vector = talloc_array(state, struct iovec, count);
471 3439150 : if (tevent_req_nomem(state->vector, req)) {
472 0 : goto post;
473 : }
474 3439150 : memcpy(state->vector, vector, sizeof(struct iovec)*count);
475 3439150 : state->count = count;
476 :
477 : /*
478 : * copy the pending buffer first
479 : */
480 3439150 : ofs = 0;
481 3439150 : left = npas->pending.iov_len;
482 3439150 : pbase = (uint8_t *)npas->pending.iov_base;
483 :
484 3439150 : while (left > 0 && state->count > 0) {
485 14174 : uint8_t *base;
486 1695261 : base = (uint8_t *)state->vector[0].iov_base;
487 1695261 : if (left < state->vector[0].iov_len) {
488 0 : memcpy(base, pbase + ofs, left);
489 :
490 0 : base += left;
491 0 : state->vector[0].iov_base = (char *) base;
492 0 : state->vector[0].iov_len -= left;
493 :
494 0 : ofs += left;
495 0 : left = 0;
496 0 : TALLOC_FREE(pbase);
497 0 : ZERO_STRUCT(npas->pending);
498 0 : break;
499 : }
500 1695261 : memcpy(base, pbase + ofs, state->vector[0].iov_len);
501 :
502 1695261 : ofs += state->vector[0].iov_len;
503 1695261 : left -= state->vector[0].iov_len;
504 1695261 : state->vector += 1;
505 1695261 : state->count -= 1;
506 :
507 1695261 : if (left == 0) {
508 1695261 : TALLOC_FREE(pbase);
509 1695261 : ZERO_STRUCT(npas->pending);
510 1695261 : break;
511 : }
512 : }
513 :
514 3439150 : if (left > 0) {
515 0 : memmove(pbase, pbase + ofs, left);
516 0 : npas->pending.iov_base = (char *) pbase;
517 0 : npas->pending.iov_len = left;
518 : /*
519 : * this cannot fail and even if it
520 : * fails we can handle it
521 : */
522 0 : pbase = talloc_realloc(npas, pbase, uint8_t, left);
523 0 : if (pbase) {
524 0 : npas->pending.iov_base = (char *) pbase;
525 : }
526 28979 : pbase = NULL;
527 : }
528 :
529 3439150 : state->ret += ofs;
530 :
531 3439150 : if (state->count == 0) {
532 1695261 : tevent_req_done(req);
533 1695261 : goto post;
534 : }
535 :
536 1743889 : ZERO_STRUCT(state->hdr);
537 1743889 : state->wait_for_hdr = false;
538 :
539 1743889 : subreq = tstream_readv_pdu_send(state,
540 : ev,
541 : npas->unix_stream,
542 : tstream_npa_readv_next_vector,
543 : state);
544 1743889 : if (tevent_req_nomem(subreq, req)) {
545 0 : goto post;
546 : }
547 1743889 : tevent_req_set_callback(subreq,
548 : tstream_npa_readv_msg_mode_handler,
549 : req);
550 :
551 1743889 : return req;
552 : }
553 :
554 : /* this can't happen */
555 0 : tevent_req_error(req, EINVAL);
556 0 : goto post;
557 :
558 1695261 : post:
559 1695261 : tevent_req_post(req, ev);
560 1695261 : return req;
561 : }
562 :
563 0 : static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
564 : {
565 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
566 : struct tevent_req);
567 0 : struct tstream_npa_readv_state *state = tevent_req_data(req,
568 : struct tstream_npa_readv_state);
569 0 : int ret;
570 0 : int sys_errno;
571 :
572 0 : ret = tstream_readv_recv(subreq, &sys_errno);
573 0 : TALLOC_FREE(subreq);
574 0 : if (ret == -1) {
575 0 : tevent_req_error(req, sys_errno);
576 0 : return;
577 : }
578 :
579 0 : state->ret = ret;
580 :
581 0 : tevent_req_done(req);
582 : }
583 :
584 5134411 : static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
585 : void *private_data,
586 : TALLOC_CTX *mem_ctx,
587 : struct iovec **_vector,
588 : size_t *_count)
589 : {
590 5134411 : struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
591 : struct tstream_npa_readv_state);
592 5134411 : struct tstream_npa *npas = tstream_context_data(state->stream,
593 : struct tstream_npa);
594 43153 : struct iovec *vector;
595 43153 : size_t count;
596 43153 : uint16_t msg_len;
597 43153 : size_t left;
598 :
599 5134411 : if (state->count == 0) {
600 1695261 : *_vector = NULL;
601 1695261 : *_count = 0;
602 1695261 : return 0;
603 : }
604 :
605 3439150 : if (!state->wait_for_hdr) {
606 : /* we need to get a message header */
607 1743889 : vector = talloc_array(mem_ctx, struct iovec, 1);
608 1743889 : if (!vector) {
609 0 : return -1;
610 : }
611 1743889 : ZERO_STRUCT(state->hdr);
612 1743889 : vector[0].iov_base = (char *) state->hdr;
613 1743889 : vector[0].iov_len = sizeof(state->hdr);
614 :
615 1743889 : count = 1;
616 :
617 1743889 : state->wait_for_hdr = true;
618 :
619 1743889 : *_vector = vector;
620 1743889 : *_count = count;
621 1743889 : return 0;
622 : }
623 :
624 : /* and now fill the callers buffers and maybe the pending buffer */
625 1695261 : state->wait_for_hdr = false;
626 :
627 1695261 : msg_len = SVAL(state->hdr, 0);
628 :
629 1695261 : if (msg_len == 0) {
630 0 : errno = EIO;
631 0 : return -1;
632 : }
633 :
634 1695261 : state->wait_for_hdr = false;
635 :
636 : /* +1 because we may need to fill the pending buffer */
637 1695261 : vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
638 1695261 : if (!vector) {
639 0 : return -1;
640 : }
641 :
642 1695261 : count = 0;
643 1695261 : left = msg_len;
644 3390522 : while (left > 0 && state->count > 0) {
645 1695261 : if (left < state->vector[0].iov_len) {
646 0 : uint8_t *base;
647 0 : base = (uint8_t *)state->vector[0].iov_base;
648 0 : vector[count].iov_base = (char *) base;
649 0 : vector[count].iov_len = left;
650 0 : count++;
651 0 : base += left;
652 0 : state->vector[0].iov_base = (char *) base;
653 0 : state->vector[0].iov_len -= left;
654 0 : break;
655 : }
656 1695261 : vector[count] = state->vector[0];
657 1695261 : count++;
658 1695261 : left -= state->vector[0].iov_len;
659 1695261 : state->vector += 1;
660 1695261 : state->count -= 1;
661 : }
662 :
663 1695261 : if (left > 0) {
664 : /*
665 : * if the message is longer than the buffers the caller
666 : * requested, we need to consume the rest of the message
667 : * into the pending buffer, where the next readv can
668 : * be served from.
669 : */
670 1695261 : npas->pending.iov_base = talloc_array(npas, char, left);
671 1695261 : if (!npas->pending.iov_base) {
672 0 : return -1;
673 : }
674 1695261 : npas->pending.iov_len = left;
675 :
676 1695261 : vector[count] = npas->pending;
677 1695261 : count++;
678 : }
679 :
680 1695261 : state->ret += (msg_len - left);
681 :
682 1695261 : *_vector = vector;
683 1695261 : *_count = count;
684 1695261 : return 0;
685 : }
686 :
687 1743850 : static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
688 : {
689 1743850 : struct tevent_req *req = tevent_req_callback_data(subreq,
690 : struct tevent_req);
691 14790 : int ret;
692 14790 : int sys_errno;
693 :
694 1743850 : ret = tstream_readv_pdu_recv(subreq, &sys_errno);
695 1743850 : TALLOC_FREE(subreq);
696 1743850 : if (ret == -1) {
697 48589 : tevent_req_error(req, sys_errno);
698 48467 : return;
699 : }
700 :
701 : /*
702 : * we do not set state->ret here as ret includes the header size.
703 : * we set it in tstream_npa_readv_pdu_next_vector()
704 : */
705 :
706 1695261 : tevent_req_done(req);
707 : }
708 :
709 3439111 : static int tstream_npa_readv_recv(struct tevent_req *req,
710 : int *perrno)
711 : {
712 3439111 : struct tstream_npa_readv_state *state = tevent_req_data(req,
713 : struct tstream_npa_readv_state);
714 28964 : int ret;
715 :
716 3439111 : ret = tsocket_simple_int_recv(req, perrno);
717 3439111 : if (ret == 0) {
718 3390522 : ret = state->ret;
719 : }
720 :
721 3439111 : tevent_req_received(req);
722 3439111 : return ret;
723 : }
724 :
725 : struct tstream_npa_writev_state {
726 : const struct iovec *vector;
727 : size_t count;
728 :
729 : /* the header for message mode */
730 : bool hdr_used;
731 : uint8_t hdr[2];
732 :
733 : int ret;
734 : };
735 :
736 : static void tstream_npa_writev_handler(struct tevent_req *subreq);
737 :
738 1693962 : static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
739 : struct tevent_context *ev,
740 : struct tstream_context *stream,
741 : const struct iovec *vector,
742 : size_t count)
743 : {
744 14174 : struct tevent_req *req;
745 14174 : struct tstream_npa_writev_state *state;
746 1693962 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
747 14174 : struct tevent_req *subreq;
748 14174 : size_t msg_len;
749 14174 : size_t i;
750 14174 : struct iovec *new_vector;
751 :
752 1693962 : req = tevent_req_create(mem_ctx, &state,
753 : struct tstream_npa_writev_state);
754 1693962 : if (!req) {
755 0 : return NULL;
756 : }
757 :
758 1693962 : state->ret = 0;
759 :
760 1693962 : if (!npas->unix_stream) {
761 0 : tevent_req_error(req, ENOTCONN);
762 0 : goto post;
763 : }
764 :
765 1693962 : switch (npas->file_type) {
766 0 : case FILE_TYPE_BYTE_MODE_PIPE:
767 0 : state->hdr_used = false;
768 0 : state->vector = vector;
769 0 : state->count = count;
770 0 : break;
771 :
772 1693962 : case FILE_TYPE_MESSAGE_MODE_PIPE:
773 : /*
774 : * we make a copy of the vector and prepend a header
775 : * with the length
776 : */
777 1693962 : new_vector = talloc_array(state, struct iovec, count + 1);
778 1693962 : if (tevent_req_nomem(new_vector, req)) {
779 0 : goto post;
780 : }
781 1693962 : new_vector[0].iov_base = (char *) state->hdr;
782 1693962 : new_vector[0].iov_len = sizeof(state->hdr);
783 1693962 : memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
784 :
785 1693962 : state->hdr_used = true;
786 1693962 : state->vector = new_vector;
787 1693962 : state->count = count + 1;
788 :
789 1693962 : msg_len = 0;
790 3387924 : for (i=0; i < count; i++) {
791 : /*
792 : * overflow check already done in tstream_writev_send
793 : */
794 1693962 : msg_len += vector[i].iov_len;
795 : }
796 :
797 1693962 : if (msg_len > UINT16_MAX) {
798 0 : tevent_req_error(req, EMSGSIZE);
799 0 : goto post;
800 : }
801 :
802 1693962 : SSVAL(state->hdr, 0, msg_len);
803 1693962 : break;
804 : }
805 :
806 1708136 : subreq = tstream_writev_send(state,
807 : ev,
808 : npas->unix_stream,
809 1679788 : state->vector,
810 1693962 : state->count);
811 1693962 : if (tevent_req_nomem(subreq, req)) {
812 0 : goto post;
813 : }
814 1693962 : tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
815 :
816 1693962 : return req;
817 :
818 0 : post:
819 0 : tevent_req_post(req, ev);
820 0 : return req;
821 : }
822 :
823 1693962 : static void tstream_npa_writev_handler(struct tevent_req *subreq)
824 : {
825 1693962 : struct tevent_req *req = tevent_req_callback_data(subreq,
826 : struct tevent_req);
827 1693962 : struct tstream_npa_writev_state *state = tevent_req_data(req,
828 : struct tstream_npa_writev_state);
829 14174 : int ret;
830 14174 : int sys_errno;
831 :
832 1693962 : ret = tstream_writev_recv(subreq, &sys_errno);
833 1693962 : TALLOC_FREE(subreq);
834 1693962 : if (ret == -1) {
835 0 : tevent_req_error(req, sys_errno);
836 0 : return;
837 : }
838 :
839 : /*
840 : * in message mode we need to hide the length
841 : * of the hdr from the caller
842 : */
843 1693962 : if (state->hdr_used) {
844 1693962 : ret -= sizeof(state->hdr);
845 : }
846 :
847 1693962 : state->ret = ret;
848 :
849 1693962 : tevent_req_done(req);
850 : }
851 :
852 1693962 : static int tstream_npa_writev_recv(struct tevent_req *req,
853 : int *perrno)
854 : {
855 1693962 : struct tstream_npa_writev_state *state = tevent_req_data(req,
856 : struct tstream_npa_writev_state);
857 14174 : int ret;
858 :
859 1693962 : ret = tsocket_simple_int_recv(req, perrno);
860 1693962 : if (ret == 0) {
861 1693962 : ret = state->ret;
862 : }
863 :
864 1693962 : tevent_req_received(req);
865 1693962 : return ret;
866 : }
867 :
868 : struct tstream_npa_disconnect_state {
869 : struct tstream_context *stream;
870 : };
871 :
872 : static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
873 :
874 0 : static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
875 : struct tevent_context *ev,
876 : struct tstream_context *stream)
877 : {
878 0 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
879 0 : struct tevent_req *req;
880 0 : struct tstream_npa_disconnect_state *state;
881 0 : struct tevent_req *subreq;
882 :
883 0 : req = tevent_req_create(mem_ctx, &state,
884 : struct tstream_npa_disconnect_state);
885 0 : if (req == NULL) {
886 0 : return NULL;
887 : }
888 :
889 0 : state->stream = stream;
890 :
891 0 : if (!npas->unix_stream) {
892 0 : tevent_req_error(req, ENOTCONN);
893 0 : goto post;
894 : }
895 :
896 0 : subreq = tstream_disconnect_send(state,
897 : ev,
898 : npas->unix_stream);
899 0 : if (tevent_req_nomem(subreq, req)) {
900 0 : goto post;
901 : }
902 0 : tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
903 :
904 0 : return req;
905 :
906 0 : post:
907 0 : tevent_req_post(req, ev);
908 0 : return req;
909 : }
910 :
911 0 : static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
912 : {
913 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
914 : struct tevent_req);
915 0 : struct tstream_npa_disconnect_state *state = tevent_req_data(req,
916 : struct tstream_npa_disconnect_state);
917 0 : struct tstream_context *stream = state->stream;
918 0 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
919 0 : int ret;
920 0 : int sys_errno;
921 :
922 0 : ret = tstream_disconnect_recv(subreq, &sys_errno);
923 0 : TALLOC_FREE(subreq);
924 0 : if (ret == -1) {
925 0 : tevent_req_error(req, sys_errno);
926 0 : return;
927 : }
928 :
929 0 : TALLOC_FREE(npas->unix_stream);
930 :
931 0 : tevent_req_done(req);
932 : }
933 :
934 0 : static int tstream_npa_disconnect_recv(struct tevent_req *req,
935 : int *perrno)
936 : {
937 0 : int ret;
938 :
939 0 : ret = tsocket_simple_int_recv(req, perrno);
940 :
941 0 : tevent_req_received(req);
942 0 : return ret;
943 : }
944 :
945 : static const struct tstream_context_ops tstream_npa_ops = {
946 : .name = "npa",
947 :
948 : .pending_bytes = tstream_npa_pending_bytes,
949 :
950 : .readv_send = tstream_npa_readv_send,
951 : .readv_recv = tstream_npa_readv_recv,
952 :
953 : .writev_send = tstream_npa_writev_send,
954 : .writev_recv = tstream_npa_writev_recv,
955 :
956 : .disconnect_send = tstream_npa_disconnect_send,
957 : .disconnect_recv = tstream_npa_disconnect_recv,
958 : };
959 :
960 88305 : int _tstream_npa_existing_stream(TALLOC_CTX *mem_ctx,
961 : struct tstream_context **transport,
962 : uint16_t file_type,
963 : struct tstream_context **_stream,
964 : const char *location)
965 : {
966 620 : struct tstream_context *stream;
967 620 : struct tstream_npa *npas;
968 :
969 88305 : switch (file_type) {
970 0 : case FILE_TYPE_BYTE_MODE_PIPE:
971 0 : break;
972 87685 : case FILE_TYPE_MESSAGE_MODE_PIPE:
973 87685 : break;
974 0 : default:
975 0 : errno = EINVAL;
976 0 : return -1;
977 : }
978 :
979 88305 : stream = tstream_context_create(mem_ctx,
980 : &tstream_npa_ops,
981 : &npas,
982 : struct tstream_npa,
983 : location);
984 88305 : if (!stream) {
985 0 : return -1;
986 : }
987 :
988 176610 : *npas = (struct tstream_npa) {
989 : .file_type = file_type,
990 88305 : .unix_stream = talloc_move(npas, transport),
991 : };
992 :
993 88305 : *_stream = stream;
994 88305 : return 0;
995 : }
996 :
997 40738 : int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
998 : int fd,
999 : uint16_t file_type,
1000 : struct tstream_context **_stream,
1001 : const char *location)
1002 : {
1003 40738 : struct tstream_context *transport = NULL;
1004 0 : int ret;
1005 :
1006 40738 : ret = _tstream_bsd_existing_socket(
1007 : mem_ctx, fd, &transport, location);
1008 40738 : if (ret == -1) {
1009 0 : return -1;
1010 : }
1011 : /* as server we want to fail early */
1012 40738 : tstream_bsd_fail_readv_first_error(transport, true);
1013 40738 : return _tstream_npa_existing_stream(
1014 : mem_ctx, &transport, file_type, _stream, location);
1015 : }
1016 :
1017 : struct tstream_npa_accept_state {
1018 : struct tevent_context *ev;
1019 : struct tstream_context *plain;
1020 : uint16_t file_type;
1021 : uint16_t device_state;
1022 : uint64_t alloc_size;
1023 :
1024 : struct named_pipe_auth_req *pipe_request;
1025 :
1026 : DATA_BLOB npa_blob;
1027 : struct iovec out_iov;
1028 :
1029 : /* results */
1030 : NTSTATUS accept_status;
1031 : struct tsocket_address *remote_client_addr;
1032 : struct tsocket_address *local_server_addr;
1033 : };
1034 :
1035 : static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1036 : static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1037 :
1038 49924 : struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1039 : struct tevent_context *ev,
1040 : struct tstream_context *plain,
1041 : uint16_t file_type,
1042 : uint16_t device_state,
1043 : uint64_t allocation_size)
1044 : {
1045 628 : struct tstream_npa_accept_state *state;
1046 628 : struct tevent_req *req, *subreq;
1047 :
1048 49924 : req = tevent_req_create(mem_ctx, &state,
1049 : struct tstream_npa_accept_state);
1050 49924 : if (req == NULL) {
1051 0 : return NULL;
1052 : }
1053 :
1054 49924 : switch (file_type) {
1055 0 : case FILE_TYPE_BYTE_MODE_PIPE:
1056 0 : break;
1057 49296 : case FILE_TYPE_MESSAGE_MODE_PIPE:
1058 49296 : break;
1059 0 : default:
1060 0 : tevent_req_error(req, EINVAL);
1061 0 : goto post;
1062 : }
1063 :
1064 49924 : state->ev = ev;
1065 49924 : state->plain = plain;
1066 49924 : state->file_type = file_type;
1067 49924 : state->device_state = device_state;
1068 49924 : state->alloc_size = allocation_size;
1069 :
1070 49924 : subreq = tstream_u32_read_send(state, ev, 0x00FFFFFF, plain);
1071 49924 : if (tevent_req_nomem(subreq, req)) {
1072 0 : goto post;
1073 : }
1074 :
1075 49924 : tevent_req_set_callback(subreq,
1076 : tstream_npa_accept_existing_reply, req);
1077 :
1078 49924 : return req;
1079 :
1080 0 : post:
1081 0 : tevent_req_post(req, ev);
1082 0 : return req;
1083 : }
1084 :
1085 49924 : static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1086 : {
1087 628 : struct tevent_req *req =
1088 49924 : tevent_req_callback_data(subreq, struct tevent_req);
1089 628 : struct tstream_npa_accept_state *state =
1090 49924 : tevent_req_data(req, struct tstream_npa_accept_state);
1091 628 : struct named_pipe_auth_req *pipe_request;
1092 628 : struct named_pipe_auth_rep pipe_reply;
1093 628 : struct named_pipe_auth_req_info8 i8;
1094 628 : enum ndr_err_code ndr_err;
1095 628 : DATA_BLOB in, out;
1096 628 : int err;
1097 628 : int ret;
1098 :
1099 49924 : err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
1100 49924 : if (err != 0) {
1101 0 : tevent_req_error(req, err);
1102 0 : return;
1103 : }
1104 49924 : if (in.length < 8) {
1105 0 : tevent_req_error(req, EMSGSIZE);
1106 0 : return;
1107 : }
1108 :
1109 49924 : if (memcmp(&in.data[4], NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1110 0 : DBG_ERR("Wrong protocol\n");
1111 : #if defined(EPROTONOSUPPORT)
1112 0 : err = EPROTONOSUPPORT;
1113 : #elif defined(EPROTO)
1114 : err = EPROTO;
1115 : #else
1116 : err = EINVAL;
1117 : #endif
1118 0 : tevent_req_error(req, err);
1119 0 : return;
1120 : }
1121 :
1122 49924 : DBG_DEBUG("Received packet of length %zu\n", in.length);
1123 49924 : dump_data(11, in.data, in.length);
1124 :
1125 49924 : ZERO_STRUCT(pipe_reply);
1126 49924 : pipe_reply.level = 0;
1127 49924 : pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1128 : /*
1129 : * TODO: check it's a root (uid == 0) pipe
1130 : */
1131 :
1132 49924 : pipe_request = talloc(state, struct named_pipe_auth_req);
1133 49924 : if (!pipe_request) {
1134 0 : DEBUG(0, ("Out of memory!\n"));
1135 0 : goto reply;
1136 : }
1137 49924 : state->pipe_request = pipe_request;
1138 :
1139 : /* parse the passed credentials */
1140 49924 : ndr_err = ndr_pull_struct_blob_all(
1141 : &in,
1142 : pipe_request,
1143 : pipe_request,
1144 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1145 49924 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1146 0 : pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1147 0 : DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1148 : nt_errstr(pipe_reply.status)));
1149 0 : goto reply;
1150 : }
1151 :
1152 49924 : if (DEBUGLVL(10)) {
1153 0 : NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1154 : }
1155 :
1156 49924 : ZERO_STRUCT(i8);
1157 :
1158 49924 : if (pipe_request->level != 8) {
1159 0 : DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1160 0 : pipe_reply.level = 0;
1161 0 : pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1162 0 : goto reply;
1163 : }
1164 :
1165 49924 : pipe_reply.level = 8;
1166 49924 : pipe_reply.status = NT_STATUS_OK;
1167 49924 : pipe_reply.info.info8.file_type = state->file_type;
1168 49924 : pipe_reply.info.info8.device_state = state->device_state;
1169 49924 : pipe_reply.info.info8.allocation_size = state->alloc_size;
1170 :
1171 49924 : i8 = pipe_request->info.info8;
1172 49924 : if (i8.local_server_addr == NULL) {
1173 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1174 0 : DEBUG(2, ("Missing local server address\n"));
1175 0 : goto reply;
1176 : }
1177 49924 : if (i8.remote_client_addr == NULL) {
1178 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1179 0 : DEBUG(2, ("Missing remote client address\n"));
1180 0 : goto reply;
1181 : }
1182 :
1183 49924 : ret = tsocket_address_inet_from_strings(state,
1184 : "ip",
1185 : i8.local_server_addr,
1186 : i8.local_server_port,
1187 : &state->local_server_addr);
1188 49924 : if (ret != 0) {
1189 0 : DEBUG(2,
1190 : ("Invalid local server address[%s:%u] - %s\n",
1191 : i8.local_server_addr,
1192 : i8.local_server_port,
1193 : strerror(errno)));
1194 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1195 0 : goto reply;
1196 : }
1197 :
1198 49924 : ret = tsocket_address_inet_from_strings(state,
1199 : "ip",
1200 : i8.remote_client_addr,
1201 : i8.remote_client_port,
1202 : &state->remote_client_addr);
1203 49924 : if (ret != 0) {
1204 0 : DEBUG(2,
1205 : ("Invalid remote client address[%s:%u] - %s\n",
1206 : i8.remote_client_addr,
1207 : i8.remote_client_port,
1208 : strerror(errno)));
1209 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1210 0 : goto reply;
1211 : }
1212 :
1213 49924 : reply:
1214 : /* create the output */
1215 49924 : ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1216 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1217 49924 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1218 0 : DEBUG(2, ("Error encoding structure: %s\n",
1219 : ndr_map_error2string(ndr_err)));
1220 0 : tevent_req_error(req, EIO);
1221 0 : return;
1222 : }
1223 :
1224 49924 : DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1225 49924 : dump_data(11, out.data, out.length);
1226 :
1227 49924 : if (DEBUGLVL(10)) {
1228 0 : NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1229 : }
1230 :
1231 49924 : state->accept_status = pipe_reply.status;
1232 :
1233 49924 : state->out_iov.iov_base = (char *) out.data;
1234 49924 : state->out_iov.iov_len = out.length;
1235 :
1236 50552 : subreq = tstream_writev_send(state, state->ev,
1237 : state->plain,
1238 49924 : &state->out_iov, 1);
1239 49924 : if (tevent_req_nomem(subreq, req)) {
1240 0 : DEBUG(0, ("no memory for tstream_writev_send\n"));
1241 0 : return;
1242 : }
1243 :
1244 49924 : tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1245 : }
1246 :
1247 49924 : static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1248 : {
1249 628 : struct tevent_req *req =
1250 49924 : tevent_req_callback_data(subreq, struct tevent_req);
1251 628 : int sys_errno;
1252 628 : int ret;
1253 :
1254 49924 : ret = tstream_writev_recv(subreq, &sys_errno);
1255 49924 : TALLOC_FREE(subreq);
1256 49924 : if (ret == -1) {
1257 0 : tevent_req_error(req, sys_errno);
1258 0 : return;
1259 : }
1260 :
1261 49924 : tevent_req_done(req);
1262 : }
1263 :
1264 : static struct named_pipe_auth_req_info8 *
1265 42111 : copy_npa_info8(TALLOC_CTX *mem_ctx,
1266 : const struct named_pipe_auth_req_info8 *src)
1267 : {
1268 42111 : struct named_pipe_auth_req_info8 *dst = NULL;
1269 0 : DATA_BLOB blob;
1270 0 : enum ndr_err_code ndr_err;
1271 :
1272 42111 : dst = talloc_zero(mem_ctx, struct named_pipe_auth_req_info8);
1273 42111 : if (dst == NULL) {
1274 0 : return NULL;
1275 : }
1276 :
1277 42111 : ndr_err = ndr_push_struct_blob(
1278 : &blob,
1279 : dst,
1280 : src,
1281 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req_info8);
1282 42111 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1283 0 : DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1284 : ndr_errstr(ndr_err));
1285 0 : TALLOC_FREE(dst);
1286 0 : return NULL;
1287 : }
1288 :
1289 42111 : ndr_err = ndr_pull_struct_blob_all(
1290 : &blob,
1291 : dst,
1292 : dst,
1293 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req_info8);
1294 42111 : TALLOC_FREE(blob.data);
1295 42111 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1296 0 : DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1297 : ndr_errstr(ndr_err));
1298 0 : TALLOC_FREE(dst);
1299 0 : return NULL;
1300 : }
1301 :
1302 42111 : return dst;
1303 : }
1304 :
1305 49924 : int _tstream_npa_accept_existing_recv(
1306 : struct tevent_req *req,
1307 : int *perrno,
1308 : TALLOC_CTX *mem_ctx,
1309 : struct tstream_context **stream,
1310 : struct named_pipe_auth_req_info8 **info8,
1311 : enum dcerpc_transport_t *transport,
1312 : struct tsocket_address **remote_client_addr,
1313 : char **_remote_client_name,
1314 : struct tsocket_address **local_server_addr,
1315 : char **local_server_name,
1316 : struct auth_session_info_transport **session_info,
1317 : const char *location)
1318 : {
1319 628 : struct tstream_npa_accept_state *state =
1320 49924 : tevent_req_data(req, struct tstream_npa_accept_state);
1321 49924 : struct named_pipe_auth_req_info8 *i8 =
1322 49924 : &state->pipe_request->info.info8;
1323 628 : struct tstream_npa *npas;
1324 628 : int ret;
1325 :
1326 49924 : ret = tsocket_simple_int_recv(req, perrno);
1327 49924 : if (ret != 0) {
1328 0 : DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1329 : strerror(*perrno)));
1330 0 : tevent_req_received(req);
1331 0 : return -1;
1332 : }
1333 :
1334 49924 : if (!NT_STATUS_IS_OK(state->accept_status)) {
1335 : #if defined(EPROTONOSUPPORT)
1336 0 : *perrno = EPROTONOSUPPORT;
1337 : #elif defined(EPROTO)
1338 : *perrno = EPROTO;
1339 : #else
1340 : *perrno = EINVAL;
1341 : #endif
1342 0 : DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1343 : nt_errstr(state->accept_status),
1344 : strerror(*perrno)));
1345 0 : tevent_req_received(req);
1346 0 : return -1;
1347 : }
1348 :
1349 49924 : *stream = tstream_context_create(mem_ctx,
1350 : &tstream_npa_ops,
1351 : &npas,
1352 : struct tstream_npa,
1353 : location);
1354 49924 : if (!*stream) {
1355 0 : *perrno = ENOMEM;
1356 0 : tevent_req_received(req);
1357 0 : return -1;
1358 : }
1359 49924 : ZERO_STRUCTP(npas);
1360 49924 : npas->unix_stream = state->plain;
1361 49924 : npas->file_type = state->file_type;
1362 :
1363 49924 : if (info8 != NULL) {
1364 : /*
1365 : * Make a full copy of "info8" because further down we
1366 : * talloc_move() away substructures from
1367 : * state->pipe_request.
1368 : */
1369 0 : struct named_pipe_auth_req_info8 *dst =
1370 42111 : copy_npa_info8(mem_ctx, i8);
1371 42111 : if (dst == NULL) {
1372 0 : *perrno = ENOMEM;
1373 0 : tevent_req_received(req);
1374 0 : return -1;
1375 : }
1376 42111 : *info8 = dst;
1377 : }
1378 :
1379 49924 : if (transport != NULL) {
1380 7813 : *transport = i8->transport;
1381 : }
1382 49924 : if (remote_client_addr != NULL) {
1383 7813 : *remote_client_addr = talloc_move(
1384 : mem_ctx, &state->remote_client_addr);
1385 : }
1386 49924 : if (_remote_client_name != NULL) {
1387 7813 : *_remote_client_name = discard_const_p(
1388 : char,
1389 : talloc_move(mem_ctx, &i8->remote_client_name));
1390 : }
1391 49924 : if (local_server_addr != NULL) {
1392 7813 : *local_server_addr = talloc_move(
1393 : mem_ctx, &state->local_server_addr);
1394 : }
1395 49924 : if (local_server_name != NULL) {
1396 7813 : *local_server_name = discard_const_p(
1397 : char,
1398 : talloc_move(mem_ctx, &i8->local_server_name));
1399 : }
1400 49924 : if (session_info != NULL) {
1401 7813 : *session_info = talloc_move(mem_ctx, &i8->session_info);
1402 : }
1403 :
1404 49924 : tevent_req_received(req);
1405 49924 : return 0;
1406 : }
|