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