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 1390 : 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 : struct tevent_req *req;
71 : struct tstream_npa_connect_state *state;
72 : struct tevent_req *subreq;
73 : int ret;
74 : enum ndr_err_code ndr_err;
75 : char *lower_case_npipe;
76 : struct named_pipe_auth_req_info7 *info7;
77 :
78 1390 : req = tevent_req_create(mem_ctx, &state,
79 : struct tstream_npa_connect_state);
80 1390 : if (!req) {
81 0 : return NULL;
82 : }
83 :
84 1390 : state->caller.ev = ev;
85 :
86 1390 : lower_case_npipe = strlower_talloc(state, npipe);
87 1390 : if (tevent_req_nomem(lower_case_npipe, req)) {
88 0 : goto post;
89 : }
90 :
91 1390 : state->unix_path = talloc_asprintf(state, "%s/%s",
92 : directory,
93 : lower_case_npipe);
94 1390 : talloc_free(lower_case_npipe);
95 1390 : if (tevent_req_nomem(state->unix_path, req)) {
96 0 : goto post;
97 : }
98 :
99 1390 : ret = tsocket_address_unix_from_path(state,
100 : "",
101 : &state->unix_laddr);
102 1390 : if (ret == -1) {
103 0 : tevent_req_error(req, errno);
104 0 : goto post;
105 : }
106 :
107 1390 : ret = tsocket_address_unix_from_path(state,
108 : state->unix_path,
109 : &state->unix_raddr);
110 1390 : if (ret == -1) {
111 0 : tevent_req_error(req, errno);
112 0 : goto post;
113 : }
114 :
115 1390 : ZERO_STRUCT(state->auth_req);
116 :
117 1390 : if (!local_server_addr) {
118 0 : tevent_req_error(req, EINVAL);
119 0 : goto post;
120 : }
121 :
122 1390 : state->auth_req.level = 7;
123 1390 : info7 = &state->auth_req.info.info7;
124 :
125 1390 : info7->transport = transport;
126 1390 : SMB_ASSERT(info7->transport == transport); /* Assert no overflow */
127 :
128 1390 : info7->remote_client_name = remote_client_name_in;
129 1390 : info7->remote_client_addr =
130 1390 : tsocket_address_inet_addr_string(remote_client_addr, state);
131 1390 : if (!info7->remote_client_addr) {
132 : /* errno might be EINVAL */
133 0 : tevent_req_error(req, errno);
134 0 : goto post;
135 : }
136 1390 : info7->remote_client_port =
137 1390 : tsocket_address_inet_port(remote_client_addr);
138 1390 : if (!info7->remote_client_name) {
139 1390 : info7->remote_client_name = info7->remote_client_addr;
140 : }
141 :
142 1390 : info7->local_server_name = local_server_name_in;
143 1390 : info7->local_server_addr =
144 1390 : tsocket_address_inet_addr_string(local_server_addr, state);
145 1390 : if (!info7->local_server_addr) {
146 : /* errno might be EINVAL */
147 0 : tevent_req_error(req, errno);
148 0 : goto post;
149 : }
150 1390 : info7->local_server_port =
151 1390 : tsocket_address_inet_port(local_server_addr);
152 1390 : if (!info7->local_server_name) {
153 1390 : info7->local_server_name = info7->local_server_addr;
154 : }
155 :
156 1390 : info7->session_info =
157 : discard_const_p(struct auth_session_info_transport,
158 : session_info);
159 :
160 1390 : if (DEBUGLVL(10)) {
161 0 : NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
162 : }
163 :
164 1390 : ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
165 1390 : state, &state->auth_req,
166 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
167 1390 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
168 0 : tevent_req_error(req, EINVAL);
169 0 : goto post;
170 : }
171 :
172 1390 : state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
173 1390 : state->auth_req_iov.iov_len = state->auth_req_blob.length;
174 :
175 1390 : subreq = tstream_unix_connect_send(state,
176 1390 : state->caller.ev,
177 1390 : state->unix_laddr,
178 1390 : state->unix_raddr);
179 1390 : if (tevent_req_nomem(subreq, req)) {
180 0 : goto post;
181 : }
182 1390 : tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
183 :
184 1390 : 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 1390 : static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
194 : {
195 950 : struct tevent_req *req =
196 1390 : tevent_req_callback_data(subreq,
197 : struct tevent_req);
198 950 : struct tstream_npa_connect_state *state =
199 1390 : tevent_req_data(req,
200 : struct tstream_npa_connect_state);
201 : int ret;
202 : int sys_errno;
203 :
204 1390 : ret = tstream_unix_connect_recv(subreq, &sys_errno,
205 : state, &state->unix_stream);
206 1390 : TALLOC_FREE(subreq);
207 1390 : if (ret == -1) {
208 153 : tevent_req_error(req, sys_errno);
209 153 : return;
210 : }
211 :
212 1237 : subreq = tstream_writev_send(state,
213 : state->caller.ev,
214 : state->unix_stream,
215 1237 : &state->auth_req_iov, 1);
216 1237 : if (tevent_req_nomem(subreq, req)) {
217 0 : return;
218 : }
219 1237 : 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 1237 : static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
225 : {
226 797 : struct tevent_req *req =
227 1237 : tevent_req_callback_data(subreq,
228 : struct tevent_req);
229 797 : struct tstream_npa_connect_state *state =
230 1237 : tevent_req_data(req,
231 : struct tstream_npa_connect_state);
232 : int ret;
233 : int sys_errno;
234 :
235 1237 : ret = tstream_writev_recv(subreq, &sys_errno);
236 1237 : TALLOC_FREE(subreq);
237 1237 : if (ret == -1) {
238 0 : tevent_req_error(req, sys_errno);
239 0 : return;
240 : }
241 :
242 1237 : subreq = tstream_u32_read_send(
243 : state, state->caller.ev, 0x00FFFFFF, state->unix_stream);
244 1237 : if (tevent_req_nomem(subreq, req)) {
245 0 : return;
246 : }
247 1237 : tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
248 : }
249 :
250 1237 : static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
251 : {
252 797 : struct tevent_req *req =
253 1237 : tevent_req_callback_data(subreq,
254 : struct tevent_req);
255 797 : struct tstream_npa_connect_state *state =
256 1237 : tevent_req_data(req,
257 : struct tstream_npa_connect_state);
258 : DATA_BLOB in;
259 : int err;
260 : enum ndr_err_code ndr_err;
261 :
262 1237 : err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
263 1237 : TALLOC_FREE(subreq);
264 1237 : if (tevent_req_error(req, err)) {
265 0 : return;
266 : }
267 :
268 1237 : DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in.length);
269 1237 : dump_data(11, in.data, in.length);
270 :
271 1237 : ndr_err = ndr_pull_struct_blob_all(
272 : &in,
273 : state,
274 1237 : &state->auth_rep,
275 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
276 :
277 1237 : 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 1237 : if (DEBUGLVL(10)) {
285 0 : NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
286 : }
287 :
288 1237 : 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 1237 : 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 1237 : 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 1237 : 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 1237 : tevent_req_done(req);
317 : }
318 :
319 1390 : 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 950 : struct tstream_npa_connect_state *state =
329 1390 : tevent_req_data(req,
330 : struct tstream_npa_connect_state);
331 : struct tstream_context *stream;
332 : struct tstream_npa *npas;
333 1390 : uint16_t device_state = 0;
334 1390 : uint64_t allocation_size = 0;
335 :
336 1390 : if (tevent_req_is_unix_error(req, perrno)) {
337 153 : tevent_req_received(req);
338 153 : return -1;
339 : }
340 :
341 1237 : stream = tstream_context_create(mem_ctx,
342 : &tstream_npa_ops,
343 : &npas,
344 : struct tstream_npa,
345 : location);
346 1237 : if (!stream) {
347 0 : *perrno = ENOMEM;
348 0 : tevent_req_received(req);
349 0 : return -1;
350 : }
351 1237 : ZERO_STRUCTP(npas);
352 :
353 1237 : npas->unix_stream = talloc_move(stream, &state->unix_stream);
354 1237 : switch (state->auth_rep.level) {
355 1237 : case 7:
356 1237 : npas->file_type = state->auth_rep.info.info7.file_type;
357 1237 : device_state = state->auth_rep.info.info7.device_state;
358 1237 : allocation_size = state->auth_rep.info.info7.allocation_size;
359 1237 : break;
360 : }
361 :
362 1237 : *_stream = stream;
363 1237 : *_file_type = npas->file_type;
364 1237 : *_device_state = device_state;
365 1237 : *_allocation_size = allocation_size;
366 1237 : tevent_req_received(req);
367 1237 : return 0;
368 : }
369 :
370 388658 : static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
371 : {
372 388658 : struct tstream_npa *npas = tstream_context_data(stream,
373 : struct tstream_npa);
374 : ssize_t ret;
375 :
376 388658 : if (!npas->unix_stream) {
377 0 : errno = ENOTCONN;
378 0 : return -1;
379 : }
380 :
381 388658 : 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 388658 : case FILE_TYPE_MESSAGE_MODE_PIPE:
387 388658 : ret = npas->pending.iov_len;
388 388658 : break;
389 :
390 0 : default:
391 0 : ret = -1;
392 : }
393 :
394 388658 : 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 542347 : 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 : struct tevent_req *req;
425 : struct tstream_npa_readv_state *state;
426 542347 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
427 : struct tevent_req *subreq;
428 : off_t ofs;
429 : size_t left;
430 : uint8_t *pbase;
431 :
432 542347 : req = tevent_req_create(mem_ctx, &state,
433 : struct tstream_npa_readv_state);
434 542347 : if (!req) {
435 0 : return NULL;
436 : }
437 :
438 542347 : state->stream = stream;
439 542347 : state->ret = 0;
440 :
441 542347 : if (!npas->unix_stream) {
442 0 : tevent_req_error(req, ENOTCONN);
443 0 : goto post;
444 : }
445 :
446 542347 : 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 542347 : 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 542347 : state->vector = talloc_array(state, struct iovec, count);
471 542347 : if (tevent_req_nomem(state->vector, req)) {
472 0 : goto post;
473 : }
474 542347 : memcpy(state->vector, vector, sizeof(struct iovec)*count);
475 542347 : state->count = count;
476 :
477 : /*
478 : * copy the pending buffer first
479 : */
480 542347 : ofs = 0;
481 542347 : left = npas->pending.iov_len;
482 542347 : pbase = (uint8_t *)npas->pending.iov_base;
483 :
484 542347 : while (left > 0 && state->count > 0) {
485 : uint8_t *base;
486 268569 : base = (uint8_t *)state->vector[0].iov_base;
487 268569 : 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 268569 : memcpy(base, pbase + ofs, state->vector[0].iov_len);
501 :
502 268569 : ofs += state->vector[0].iov_len;
503 268569 : left -= state->vector[0].iov_len;
504 268569 : state->vector += 1;
505 268569 : state->count -= 1;
506 :
507 268569 : if (left == 0) {
508 268569 : TALLOC_FREE(pbase);
509 268569 : ZERO_STRUCT(npas->pending);
510 268569 : break;
511 : }
512 : }
513 :
514 542347 : 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 0 : pbase = NULL;
527 : }
528 :
529 542347 : state->ret += ofs;
530 :
531 542347 : if (state->count == 0) {
532 268569 : tevent_req_done(req);
533 268569 : goto post;
534 : }
535 :
536 273778 : ZERO_STRUCT(state->hdr);
537 273778 : state->wait_for_hdr = false;
538 :
539 273778 : subreq = tstream_readv_pdu_send(state,
540 : ev,
541 : npas->unix_stream,
542 : tstream_npa_readv_next_vector,
543 : state);
544 273778 : if (tevent_req_nomem(subreq, req)) {
545 0 : goto post;
546 : }
547 273778 : tevent_req_set_callback(subreq,
548 : tstream_npa_readv_msg_mode_handler,
549 : req);
550 :
551 273778 : return req;
552 : }
553 :
554 : /* this can't happen */
555 0 : tevent_req_error(req, EINVAL);
556 0 : goto post;
557 :
558 268569 : post:
559 268569 : tevent_req_post(req, ev);
560 268569 : 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 : int ret;
570 : 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 810916 : 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 810916 : struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
591 : struct tstream_npa_readv_state);
592 810916 : struct tstream_npa *npas = tstream_context_data(state->stream,
593 : struct tstream_npa);
594 : struct iovec *vector;
595 : size_t count;
596 : uint16_t msg_len;
597 : size_t left;
598 :
599 810916 : if (state->count == 0) {
600 268569 : *_vector = NULL;
601 268569 : *_count = 0;
602 268569 : return 0;
603 : }
604 :
605 542347 : if (!state->wait_for_hdr) {
606 : /* we need to get a message header */
607 273778 : vector = talloc_array(mem_ctx, struct iovec, 1);
608 273778 : if (!vector) {
609 0 : return -1;
610 : }
611 273778 : ZERO_STRUCT(state->hdr);
612 273778 : vector[0].iov_base = (char *) state->hdr;
613 273778 : vector[0].iov_len = sizeof(state->hdr);
614 :
615 273778 : count = 1;
616 :
617 273778 : state->wait_for_hdr = true;
618 :
619 273778 : *_vector = vector;
620 273778 : *_count = count;
621 273778 : return 0;
622 : }
623 :
624 : /* and now fill the callers buffers and maybe the pending buffer */
625 268569 : state->wait_for_hdr = false;
626 :
627 268569 : msg_len = SVAL(state->hdr, 0);
628 :
629 268569 : if (msg_len == 0) {
630 0 : errno = EIO;
631 0 : return -1;
632 : }
633 :
634 268569 : state->wait_for_hdr = false;
635 :
636 : /* +1 because we may need to fill the pending buffer */
637 268569 : vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
638 268569 : if (!vector) {
639 0 : return -1;
640 : }
641 :
642 268569 : count = 0;
643 268569 : left = msg_len;
644 742691 : while (left > 0 && state->count > 0) {
645 268569 : if (left < state->vector[0].iov_len) {
646 : 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 268569 : vector[count] = state->vector[0];
657 268569 : count++;
658 268569 : left -= state->vector[0].iov_len;
659 268569 : state->vector += 1;
660 268569 : state->count -= 1;
661 : }
662 :
663 268569 : 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 268569 : npas->pending.iov_base = talloc_array(npas, char, left);
671 268569 : if (!npas->pending.iov_base) {
672 0 : return -1;
673 : }
674 268569 : npas->pending.iov_len = left;
675 :
676 268569 : vector[count] = npas->pending;
677 268569 : count++;
678 : }
679 :
680 268569 : state->ret += (msg_len - left);
681 :
682 268569 : *_vector = vector;
683 268569 : *_count = count;
684 268569 : return 0;
685 : }
686 :
687 273768 : static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
688 : {
689 273768 : struct tevent_req *req = tevent_req_callback_data(subreq,
690 : struct tevent_req);
691 : int ret;
692 : int sys_errno;
693 :
694 273768 : ret = tstream_readv_pdu_recv(subreq, &sys_errno);
695 273768 : TALLOC_FREE(subreq);
696 273768 : if (ret == -1) {
697 5199 : tevent_req_error(req, sys_errno);
698 5101 : 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 268569 : tevent_req_done(req);
707 : }
708 :
709 542337 : static int tstream_npa_readv_recv(struct tevent_req *req,
710 : int *perrno)
711 : {
712 542337 : struct tstream_npa_readv_state *state = tevent_req_data(req,
713 : struct tstream_npa_readv_state);
714 : int ret;
715 :
716 542337 : ret = tsocket_simple_int_recv(req, perrno);
717 542337 : if (ret == 0) {
718 537138 : ret = state->ret;
719 : }
720 :
721 542337 : tevent_req_received(req);
722 542337 : 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 268421 : 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 : struct tevent_req *req;
745 : struct tstream_npa_writev_state *state;
746 268421 : struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
747 : struct tevent_req *subreq;
748 : size_t msg_len;
749 : size_t i;
750 : struct iovec *new_vector;
751 :
752 268421 : req = tevent_req_create(mem_ctx, &state,
753 : struct tstream_npa_writev_state);
754 268421 : if (!req) {
755 0 : return NULL;
756 : }
757 :
758 268421 : state->ret = 0;
759 :
760 268421 : if (!npas->unix_stream) {
761 0 : tevent_req_error(req, ENOTCONN);
762 0 : goto post;
763 : }
764 :
765 268421 : 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 268421 : 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 268421 : new_vector = talloc_array(state, struct iovec, count + 1);
778 268421 : if (tevent_req_nomem(new_vector, req)) {
779 0 : goto post;
780 : }
781 268421 : new_vector[0].iov_base = (char *) state->hdr;
782 268421 : new_vector[0].iov_len = sizeof(state->hdr);
783 268421 : memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
784 :
785 268421 : state->hdr_used = true;
786 268421 : state->vector = new_vector;
787 268421 : state->count = count + 1;
788 :
789 268421 : msg_len = 0;
790 536842 : for (i=0; i < count; i++) {
791 : /*
792 : * overflow check already done in tstream_writev_send
793 : */
794 268421 : msg_len += vector[i].iov_len;
795 : }
796 :
797 268421 : if (msg_len > UINT16_MAX) {
798 0 : tevent_req_error(req, EMSGSIZE);
799 0 : goto post;
800 : }
801 :
802 268421 : SSVAL(state->hdr, 0, msg_len);
803 268421 : break;
804 : }
805 :
806 473884 : subreq = tstream_writev_send(state,
807 : ev,
808 : npas->unix_stream,
809 268421 : state->vector,
810 268421 : state->count);
811 268421 : if (tevent_req_nomem(subreq, req)) {
812 0 : goto post;
813 : }
814 268421 : tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
815 :
816 268421 : return req;
817 :
818 0 : post:
819 0 : tevent_req_post(req, ev);
820 0 : return req;
821 : }
822 :
823 268421 : static void tstream_npa_writev_handler(struct tevent_req *subreq)
824 : {
825 268421 : struct tevent_req *req = tevent_req_callback_data(subreq,
826 : struct tevent_req);
827 268421 : struct tstream_npa_writev_state *state = tevent_req_data(req,
828 : struct tstream_npa_writev_state);
829 : int ret;
830 : int sys_errno;
831 :
832 268421 : ret = tstream_writev_recv(subreq, &sys_errno);
833 268421 : TALLOC_FREE(subreq);
834 268421 : 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 268421 : if (state->hdr_used) {
844 268421 : ret -= sizeof(state->hdr);
845 : }
846 :
847 268421 : state->ret = ret;
848 :
849 268421 : tevent_req_done(req);
850 : }
851 :
852 268421 : static int tstream_npa_writev_recv(struct tevent_req *req,
853 : int *perrno)
854 : {
855 268421 : struct tstream_npa_writev_state *state = tevent_req_data(req,
856 : struct tstream_npa_writev_state);
857 : int ret;
858 :
859 268421 : ret = tsocket_simple_int_recv(req, perrno);
860 268421 : if (ret == 0) {
861 268421 : ret = state->ret;
862 : }
863 :
864 268421 : tevent_req_received(req);
865 268421 : 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 : struct tevent_req *req;
880 : struct tstream_npa_disconnect_state *state;
881 : 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 : int ret;
920 : 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 : 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 3804 : 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 : struct tstream_context *stream;
967 : struct tstream_npa *npas;
968 :
969 3804 : switch (file_type) {
970 0 : case FILE_TYPE_BYTE_MODE_PIPE:
971 0 : break;
972 3804 : case FILE_TYPE_MESSAGE_MODE_PIPE:
973 3804 : break;
974 0 : default:
975 0 : errno = EINVAL;
976 0 : return -1;
977 : }
978 :
979 3804 : stream = tstream_context_create(mem_ctx,
980 : &tstream_npa_ops,
981 : &npas,
982 : struct tstream_npa,
983 : location);
984 3804 : if (!stream) {
985 0 : return -1;
986 : }
987 :
988 7608 : *npas = (struct tstream_npa) {
989 : .file_type = file_type,
990 3804 : .unix_stream = talloc_move(npas, transport),
991 : };
992 :
993 3804 : *_stream = stream;
994 3804 : return 0;
995 : }
996 :
997 283 : 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 283 : struct tstream_context *transport = NULL;
1004 : int ret;
1005 :
1006 283 : ret = _tstream_bsd_existing_socket(
1007 : mem_ctx, fd, &transport, location);
1008 283 : if (ret == -1) {
1009 0 : return -1;
1010 : }
1011 283 : return _tstream_npa_existing_stream(
1012 : mem_ctx, &transport, file_type, _stream, location);
1013 : }
1014 :
1015 : struct tstream_npa_accept_state {
1016 : struct tevent_context *ev;
1017 : struct tstream_context *plain;
1018 : uint16_t file_type;
1019 : uint16_t device_state;
1020 : uint64_t alloc_size;
1021 :
1022 : struct named_pipe_auth_req *pipe_request;
1023 :
1024 : DATA_BLOB npa_blob;
1025 : struct iovec out_iov;
1026 :
1027 : /* results */
1028 : NTSTATUS accept_status;
1029 : struct tsocket_address *remote_client_addr;
1030 : struct tsocket_address *local_server_addr;
1031 : };
1032 :
1033 : static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1034 : static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1035 :
1036 5337 : struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1037 : struct tevent_context *ev,
1038 : struct tstream_context *plain,
1039 : uint16_t file_type,
1040 : uint16_t device_state,
1041 : uint64_t allocation_size)
1042 : {
1043 : struct tstream_npa_accept_state *state;
1044 : struct tevent_req *req, *subreq;
1045 :
1046 5337 : req = tevent_req_create(mem_ctx, &state,
1047 : struct tstream_npa_accept_state);
1048 5337 : if (req == NULL) {
1049 0 : return NULL;
1050 : }
1051 :
1052 5337 : switch (file_type) {
1053 0 : case FILE_TYPE_BYTE_MODE_PIPE:
1054 0 : break;
1055 5337 : case FILE_TYPE_MESSAGE_MODE_PIPE:
1056 5337 : break;
1057 0 : default:
1058 0 : tevent_req_error(req, EINVAL);
1059 0 : goto post;
1060 : }
1061 :
1062 5337 : state->ev = ev;
1063 5337 : state->plain = plain;
1064 5337 : state->file_type = file_type;
1065 5337 : state->device_state = device_state;
1066 5337 : state->alloc_size = allocation_size;
1067 :
1068 5337 : subreq = tstream_u32_read_send(state, ev, 0x00FFFFFF, plain);
1069 5337 : if (tevent_req_nomem(subreq, req)) {
1070 0 : goto post;
1071 : }
1072 :
1073 5337 : tevent_req_set_callback(subreq,
1074 : tstream_npa_accept_existing_reply, req);
1075 :
1076 5337 : return req;
1077 :
1078 0 : post:
1079 0 : tevent_req_post(req, ev);
1080 0 : return req;
1081 : }
1082 :
1083 5337 : static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1084 : {
1085 3822 : struct tevent_req *req =
1086 5337 : tevent_req_callback_data(subreq, struct tevent_req);
1087 3822 : struct tstream_npa_accept_state *state =
1088 5337 : tevent_req_data(req, struct tstream_npa_accept_state);
1089 : struct named_pipe_auth_req *pipe_request;
1090 : struct named_pipe_auth_rep pipe_reply;
1091 : struct named_pipe_auth_req_info7 i7;
1092 : enum ndr_err_code ndr_err;
1093 : DATA_BLOB in, out;
1094 : int err;
1095 : int ret;
1096 :
1097 5337 : err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
1098 5337 : if (err != 0) {
1099 0 : tevent_req_error(req, err);
1100 0 : return;
1101 : }
1102 5337 : if (in.length < 8) {
1103 0 : tevent_req_error(req, EMSGSIZE);
1104 0 : return;
1105 : }
1106 :
1107 5337 : if (memcmp(&in.data[4], NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1108 0 : DBG_ERR("Wrong protocol\n");
1109 : #if defined(EPROTONOSUPPORT)
1110 0 : err = EPROTONOSUPPORT;
1111 : #elif defined(EPROTO)
1112 : err = EPROTO;
1113 : #else
1114 : err = EINVAL;
1115 : #endif
1116 0 : tevent_req_error(req, err);
1117 0 : return;
1118 : }
1119 :
1120 5337 : DBG_DEBUG("Received packet of length %zu\n", in.length);
1121 5337 : dump_data(11, in.data, in.length);
1122 :
1123 5337 : ZERO_STRUCT(pipe_reply);
1124 5337 : pipe_reply.level = 0;
1125 5337 : pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1126 : /*
1127 : * TODO: check it's a root (uid == 0) pipe
1128 : */
1129 :
1130 5337 : pipe_request = talloc(state, struct named_pipe_auth_req);
1131 5337 : if (!pipe_request) {
1132 0 : DEBUG(0, ("Out of memory!\n"));
1133 0 : goto reply;
1134 : }
1135 5337 : state->pipe_request = pipe_request;
1136 :
1137 : /* parse the passed credentials */
1138 5337 : ndr_err = ndr_pull_struct_blob_all(
1139 : &in,
1140 : pipe_request,
1141 : pipe_request,
1142 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1143 5337 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1144 0 : pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1145 0 : DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1146 : nt_errstr(pipe_reply.status)));
1147 0 : goto reply;
1148 : }
1149 :
1150 5337 : if (DEBUGLVL(10)) {
1151 0 : NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1152 : }
1153 :
1154 5337 : ZERO_STRUCT(i7);
1155 :
1156 5337 : if (pipe_request->level != 7) {
1157 0 : DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1158 0 : pipe_reply.level = 0;
1159 0 : pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1160 0 : goto reply;
1161 : }
1162 :
1163 5337 : pipe_reply.level = 7;
1164 5337 : pipe_reply.status = NT_STATUS_OK;
1165 5337 : pipe_reply.info.info7.file_type = state->file_type;
1166 5337 : pipe_reply.info.info7.device_state = state->device_state;
1167 5337 : pipe_reply.info.info7.allocation_size = state->alloc_size;
1168 :
1169 5337 : i7 = pipe_request->info.info7;
1170 5337 : if (i7.local_server_addr == NULL) {
1171 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1172 0 : DEBUG(2, ("Missing local server address\n"));
1173 0 : goto reply;
1174 : }
1175 5337 : if (i7.remote_client_addr == NULL) {
1176 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1177 0 : DEBUG(2, ("Missing remote client address\n"));
1178 0 : goto reply;
1179 : }
1180 :
1181 5337 : ret = tsocket_address_inet_from_strings(state,
1182 : "ip",
1183 : i7.local_server_addr,
1184 : i7.local_server_port,
1185 : &state->local_server_addr);
1186 5337 : if (ret != 0) {
1187 0 : DEBUG(2,
1188 : ("Invalid local server address[%s:%u] - %s\n",
1189 : i7.local_server_addr,
1190 : i7.local_server_port,
1191 : strerror(errno)));
1192 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1193 0 : goto reply;
1194 : }
1195 :
1196 5337 : ret = tsocket_address_inet_from_strings(state,
1197 : "ip",
1198 : i7.remote_client_addr,
1199 : i7.remote_client_port,
1200 : &state->remote_client_addr);
1201 5337 : if (ret != 0) {
1202 0 : DEBUG(2,
1203 : ("Invalid remote client address[%s:%u] - %s\n",
1204 : i7.remote_client_addr,
1205 : i7.remote_client_port,
1206 : strerror(errno)));
1207 0 : pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1208 0 : goto reply;
1209 : }
1210 :
1211 9159 : reply:
1212 : /* create the output */
1213 5337 : ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1214 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1215 5337 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1216 0 : DEBUG(2, ("Error encoding structure: %s",
1217 : ndr_map_error2string(ndr_err)));
1218 0 : tevent_req_error(req, EIO);
1219 0 : return;
1220 : }
1221 :
1222 5337 : DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1223 5337 : dump_data(11, out.data, out.length);
1224 :
1225 5337 : if (DEBUGLVL(10)) {
1226 0 : NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1227 : }
1228 :
1229 5337 : state->accept_status = pipe_reply.status;
1230 :
1231 5337 : state->out_iov.iov_base = (char *) out.data;
1232 5337 : state->out_iov.iov_len = out.length;
1233 :
1234 5337 : subreq = tstream_writev_send(state, state->ev,
1235 : state->plain,
1236 5337 : &state->out_iov, 1);
1237 5337 : if (tevent_req_nomem(subreq, req)) {
1238 0 : DEBUG(0, ("no memory for tstream_writev_send"));
1239 0 : return;
1240 : }
1241 :
1242 5337 : tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1243 : }
1244 :
1245 5337 : static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1246 : {
1247 3822 : struct tevent_req *req =
1248 5337 : tevent_req_callback_data(subreq, struct tevent_req);
1249 : int sys_errno;
1250 : int ret;
1251 :
1252 5337 : ret = tstream_writev_recv(subreq, &sys_errno);
1253 5337 : TALLOC_FREE(subreq);
1254 5337 : if (ret == -1) {
1255 0 : tevent_req_error(req, sys_errno);
1256 0 : return;
1257 : }
1258 :
1259 5337 : tevent_req_done(req);
1260 : }
1261 :
1262 : static struct named_pipe_auth_req_info7 *
1263 414 : copy_npa_info7(TALLOC_CTX *mem_ctx,
1264 : const struct named_pipe_auth_req_info7 *src)
1265 : {
1266 414 : struct named_pipe_auth_req_info7 *dst = NULL;
1267 : DATA_BLOB blob;
1268 : enum ndr_err_code ndr_err;
1269 :
1270 414 : dst = talloc_zero(mem_ctx, struct named_pipe_auth_req_info7);
1271 414 : if (dst == NULL) {
1272 0 : return NULL;
1273 : }
1274 :
1275 414 : ndr_err = ndr_push_struct_blob(
1276 : &blob,
1277 : dst,
1278 : src,
1279 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req_info7);
1280 414 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1281 0 : DBG_WARNING("ndr_push_named_pipe_auth_req_info7 failed: %s\n",
1282 : ndr_errstr(ndr_err));
1283 0 : TALLOC_FREE(dst);
1284 0 : return NULL;
1285 : }
1286 :
1287 414 : ndr_err = ndr_pull_struct_blob_all(
1288 : &blob,
1289 : dst,
1290 : dst,
1291 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req_info7);
1292 414 : TALLOC_FREE(blob.data);
1293 414 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1294 0 : DBG_WARNING("ndr_push_named_pipe_auth_req_info7 failed: %s\n",
1295 : ndr_errstr(ndr_err));
1296 0 : TALLOC_FREE(dst);
1297 0 : return NULL;
1298 : }
1299 :
1300 414 : return dst;
1301 : }
1302 :
1303 5337 : int _tstream_npa_accept_existing_recv(
1304 : struct tevent_req *req,
1305 : int *perrno,
1306 : TALLOC_CTX *mem_ctx,
1307 : struct tstream_context **stream,
1308 : struct named_pipe_auth_req_info7 **info7,
1309 : enum dcerpc_transport_t *transport,
1310 : struct tsocket_address **remote_client_addr,
1311 : char **_remote_client_name,
1312 : struct tsocket_address **local_server_addr,
1313 : char **local_server_name,
1314 : struct auth_session_info_transport **session_info,
1315 : const char *location)
1316 : {
1317 3822 : struct tstream_npa_accept_state *state =
1318 5337 : tevent_req_data(req, struct tstream_npa_accept_state);
1319 5337 : struct named_pipe_auth_req_info7 *i7 =
1320 5337 : &state->pipe_request->info.info7;
1321 : struct tstream_npa *npas;
1322 : int ret;
1323 :
1324 5337 : ret = tsocket_simple_int_recv(req, perrno);
1325 5337 : if (ret != 0) {
1326 0 : DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1327 : strerror(*perrno)));
1328 0 : tevent_req_received(req);
1329 0 : return -1;
1330 : }
1331 :
1332 5337 : if (!NT_STATUS_IS_OK(state->accept_status)) {
1333 : #if defined(EPROTONOSUPPORT)
1334 0 : *perrno = EPROTONOSUPPORT;
1335 : #elif defined(EPROTO)
1336 : *perrno = EPROTO;
1337 : #else
1338 : *perrno = EINVAL;
1339 : #endif
1340 0 : DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1341 : nt_errstr(state->accept_status),
1342 : strerror(*perrno)));
1343 0 : tevent_req_received(req);
1344 0 : return -1;
1345 : }
1346 :
1347 5337 : *stream = tstream_context_create(mem_ctx,
1348 : &tstream_npa_ops,
1349 : &npas,
1350 : struct tstream_npa,
1351 : location);
1352 5337 : if (!*stream) {
1353 0 : *perrno = ENOMEM;
1354 0 : tevent_req_received(req);
1355 0 : return -1;
1356 : }
1357 5337 : ZERO_STRUCTP(npas);
1358 5337 : npas->unix_stream = state->plain;
1359 5337 : npas->file_type = state->file_type;
1360 :
1361 5337 : if (info7 != NULL) {
1362 : /*
1363 : * Make a full copy of "info7" because further down we
1364 : * talloc_move() away substructures from
1365 : * state->pipe_request.
1366 : */
1367 246 : struct named_pipe_auth_req_info7 *dst =
1368 168 : copy_npa_info7(mem_ctx, i7);
1369 414 : if (dst == NULL) {
1370 0 : *perrno = ENOMEM;
1371 0 : tevent_req_received(req);
1372 0 : return -1;
1373 : }
1374 414 : *info7 = dst;
1375 : }
1376 :
1377 5337 : if (transport != NULL) {
1378 4923 : *transport = i7->transport;
1379 : }
1380 5337 : if (remote_client_addr != NULL) {
1381 4923 : *remote_client_addr = talloc_move(
1382 : mem_ctx, &state->remote_client_addr);
1383 : }
1384 5337 : if (_remote_client_name != NULL) {
1385 4923 : *_remote_client_name = discard_const_p(
1386 : char,
1387 : talloc_move(mem_ctx, &i7->remote_client_name));
1388 : }
1389 5337 : if (local_server_addr != NULL) {
1390 4923 : *local_server_addr = talloc_move(
1391 : mem_ctx, &state->local_server_addr);
1392 : }
1393 5337 : if (local_server_name != NULL) {
1394 4923 : *local_server_name = discard_const_p(
1395 : char,
1396 : talloc_move(mem_ctx, &i7->local_server_name));
1397 : }
1398 5337 : if (session_info != NULL) {
1399 4923 : *session_info = talloc_move(mem_ctx, &i7->session_info);
1400 : }
1401 :
1402 5337 : tevent_req_received(req);
1403 5337 : return 0;
1404 : }
|