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