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