STEP01: global fragment checking librpc/rpc/dcerpc_connection.
[metze/samba/wip.git] / librpc / rpc / dcerpc_connection.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  DCERPC client routines
4  *
5  *  Copyright (C) Stefan Metzmacher 2011
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "system/network.h"
23 #include <tevent.h>
24 #include "lib/util/tevent_ntstatus.h"
25 #include "lib/tsocket/tsocket.h"
26 #include "librpc/gen_ndr/ndr_dcerpc.h"
27 #include "source3/librpc/rpc/dcerpc.h"
28 #include "source4/librpc/rpc/dcerpc.h"
29 #include "auth/gensec/gensec.h"
30 #include "librpc/rpc/dcerpc_connection.h"
31 #include "../lib/util/dlinklist.h"
32
33 struct dcerpc_association;
34 struct dcerpc_connection;
35 struct dcerpc_security;
36 struct dcerpc_presentation;
37 struct dcerpc_call;
38
39 struct dcerpc_association {
40         uint32_t assoc_group_id;
41         uint16_t client_features;
42         uint16_t features;
43         bool negotiate_done;
44         uint32_t next_call_id;
45 };
46
47 struct dcerpc_connection {
48         struct dcerpc_association *assoc;
49
50         struct {
51                 struct tstream_context *stream;
52                 dcerpc_connection_use_trans_fn use_trans_fn;
53                 struct tevent_queue *write_queue;
54         } transport;
55
56         struct {
57                 uint16_t max_xmit_frag;
58                 uint16_t max_recv_frag;
59                 bool concurrent_multiplex;
60                 bool bind_done;
61         } features;
62
63         uint32_t next_sec_context_id;
64         uint16_t next_pres_context_id;
65
66         struct {
67                 struct tevent_queue *out_queue;
68                 struct dcerpc_call *list;
69                 struct dcerpc_call *active;
70                 struct dcerpc_call *new_call;
71         } calls;
72
73         struct {
74                 struct tevent_context *ev;
75                 struct tevent_req *subreq;
76         } loop;
77 };
78
79 struct dcerpc_security {
80         uint32_t context_id;
81         enum dcerpc_AuthType auth_type;
82         enum dcerpc_AuthLevel auth_level;
83         struct gensec_security *gensec;
84         bool client_hdr_signing;
85         bool hdr_signing;
86         bool verified_bitmask1;
87 };
88
89 struct dcerpc_presentation {
90         uint16_t context_id;
91         const struct ndr_interface_table *table;
92         struct ndr_syntax_id transfer;
93         struct {
94                 struct dcerpc_ctx_list req;
95                 struct dcerpc_ack_ctx ack;
96         } negotiate;
97         bool verified_pcontext;
98 };
99
100 struct dcerpc_call {
101         struct dcerpc_call *prev, *next;
102         uint32_t call_id;
103
104         struct dcerpc_security *sec;
105         struct dcerpc_presentation *pres;
106
107         struct {
108                 void *private_data;
109                 NTSTATUS (*handler)(void *private_data,
110                                     struct ncacn_packet *pkt,
111                                     DATA_BLOB frag);
112         } incoming;
113 };
114
115 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
116                                                      uint16_t client_features)
117 {
118         struct dcerpc_association *assoc;
119
120         assoc = talloc_zero(mem_ctx, struct dcerpc_association);
121         if (assoc == NULL) {
122                 return NULL;
123         }
124
125         assoc->next_call_id = 1;
126
127         assoc->client_features = client_features;
128
129         return assoc;
130 }
131
132 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
133                                         struct dcerpc_association *assoc,
134                                         struct tstream_context **stream)
135 {
136         struct dcerpc_connection *conn;
137
138         conn = talloc_zero(mem_ctx, struct dcerpc_connection);
139         if (conn == NULL) {
140                 return NULL;
141         }
142         conn->assoc = assoc;
143
144         conn->transport.stream = talloc_move(conn, stream);
145         conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
146         if (conn->transport.write_queue == NULL) {
147                 talloc_free(conn);
148                 return NULL;
149         }
150
151         conn->features.max_xmit_frag = 4280;
152         conn->features.max_recv_frag = 4280;
153
154         conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
155         if (conn->calls.out_queue == NULL) {
156                 talloc_free(conn);
157                 return NULL;
158         }
159
160         return conn;
161 }
162
163 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
164                                         dcerpc_connection_use_trans_fn fn)
165 {
166         conn->transport.use_trans_fn = fn;
167 }
168
169 struct dcerpc_security *dcerpc_security_allocate(
170                                         TALLOC_CTX *mem_ctx,
171                                         struct dcerpc_connection *conn,
172                                         enum dcerpc_AuthType auth_type,
173                                         enum dcerpc_AuthLevel auth_level,
174                                         struct gensec_security **gensec)
175 {
176         struct dcerpc_security *sec;
177
178         sec = talloc_zero(mem_ctx, struct dcerpc_security);
179         if (sec == NULL) {
180                 return NULL;
181         }
182
183         sec->context_id = conn->next_sec_context_id++;
184         sec->auth_type = auth_type;
185         sec->auth_level = auth_level;
186
187         if (gensec != NULL) {
188                 sec->gensec = talloc_move(sec, gensec);
189         }
190
191         return sec;
192 }
193
194 struct dcerpc_presentation *dcerpc_presentation_allocate(
195                                         TALLOC_CTX *mem_ctx,
196                                         struct dcerpc_connection *conn,
197                                         const struct ndr_interface_table *table,
198                                         const struct ndr_syntax_id *transfer)
199 {
200         struct dcerpc_presentation *pres;
201
202         pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
203         if (pres == NULL) {
204                 return NULL;
205         }
206
207         pres->context_id = conn->next_pres_context_id++;
208         pres->table = table;
209         pres->transfer = *transfer;
210
211         pres->negotiate.req.abstract_syntax = table->syntax_id;
212         pres->negotiate.req.context_id = pres->context_id;
213         pres->negotiate.req.num_transfer_syntaxes = 1;
214         pres->negotiate.req.transfer_syntaxes = &pres->transfer;
215
216         pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
217         pres->negotiate.ack.reason.value =
218                 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
219
220         return pres;
221 }
222
223 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
224                                          struct dcerpc_association *assoc,
225                                          struct dcerpc_security *sec,
226                                          struct dcerpc_presentation *pres)
227 {
228         struct dcerpc_call *call;
229
230         call = talloc_zero(mem_ctx, struct dcerpc_call);
231         if (call == NULL) {
232                 return NULL;
233         }
234
235         call->call_id = assoc->next_call_id++;
236
237         call->sec = sec;
238         call->pres = pres;
239
240         return call;
241 }
242
243 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
244                                        size_t header_len,
245                                        size_t data_left,
246                                        size_t max_xmit_frag,
247                                        size_t pad_alignment,
248                                        size_t *data_to_send,
249                                        size_t *frag_len,
250                                        size_t *auth_len,
251                                        size_t *pad_len)
252 {
253         size_t max_len;
254         size_t mod_len;
255
256         /* no auth token cases first */
257         switch (sec->auth_level) {
258         case DCERPC_AUTH_LEVEL_NONE:
259         case DCERPC_AUTH_LEVEL_CONNECT:
260         case DCERPC_AUTH_LEVEL_PACKET:
261                 max_len = max_xmit_frag - header_len;
262                 *data_to_send = MIN(max_len, data_left);
263                 *pad_len = 0;
264                 *auth_len = 0;
265                 *frag_len = header_len + *data_to_send;
266                 return NT_STATUS_OK;
267
268         case DCERPC_AUTH_LEVEL_PRIVACY:
269         case DCERPC_AUTH_LEVEL_INTEGRITY:
270                 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
271                         return NT_STATUS_INVALID_PARAMETER_MIX;
272                 }
273                 if (sec->gensec == NULL) {
274                         return NT_STATUS_INVALID_PARAMETER_MIX;
275                 }
276                 break;
277
278         default:
279                 return NT_STATUS_INVALID_PARAMETER;
280         }
281
282
283         /* Sign/seal case, calculate auth and pad lengths */
284
285         max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
286
287         *auth_len = gensec_sig_size(sec->gensec, max_len);
288
289         max_len -= *auth_len;
290
291         *data_to_send = MIN(max_len, data_left);
292
293         mod_len = (header_len + *data_to_send) % pad_alignment;
294         if (mod_len) {
295                 *pad_len = pad_alignment - mod_len;
296         } else {
297                 *pad_len = 0;
298         }
299
300         if (*data_to_send + *pad_len > max_len) {
301                 *data_to_send -= pad_alignment;
302         }
303
304         *frag_len = header_len + *data_to_send + *pad_len
305                         + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
306
307         return NT_STATUS_OK;
308 }
309
310 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
311                                        TALLOC_CTX *mem_ctx,
312                                        struct ncacn_packet *pkt,
313                                        struct dcerpc_auth *auth_info)
314 {
315         struct ndr_push *ndr;
316         enum ndr_err_code ndr_err;
317
318         ndr = ndr_push_init_ctx(mem_ctx);
319         if (!ndr) {
320                 return NT_STATUS_NO_MEMORY;
321         }
322
323         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
324                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
325         }
326
327         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
328                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
329         }
330
331         if (auth_info) {
332                 pkt->auth_length = auth_info->credentials.length;
333         } else {
334         //      pkt->auth_length = 0;
335         }
336
337         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
338         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
339                 return ndr_map_error2ntstatus(ndr_err);
340         }
341
342         if (auth_info) {
343 #if 0
344                 /* the s3 rpc server doesn't handle auth padding in
345                    bind requests. Use zero auth padding to keep us
346                    working with old servers */
347                 uint32_t offset = ndr->offset;
348                 ndr_err = ndr_push_align(ndr, 16);
349                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
350                         return ndr_map_error2ntstatus(ndr_err);
351                 }
352                 auth_info->auth_pad_length = ndr->offset - offset;
353 #else
354                 auth_info->auth_pad_length = 0;
355 #endif
356                 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
357                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
358                         return ndr_map_error2ntstatus(ndr_err);
359                 }
360         }
361
362         *blob = ndr_push_blob(ndr);
363
364         /* fill in the frag length */
365         dcerpc_set_frag_length(blob, blob->length);
366
367         return NT_STATUS_OK;
368 }
369
370 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
371                                          enum dcerpc_pkt_type ptype,
372                                          uint8_t pfc_flags,
373                                          uint16_t auth_length,
374                                          uint32_t call_id,
375                                          union dcerpc_payload *u,
376                                          DATA_BLOB *blob)
377 {
378         struct ncacn_packet r;
379         NTSTATUS status;
380
381         r.rpc_vers              = 5;
382         r.rpc_vers_minor        = 0;
383         r.ptype                 = ptype;
384         r.pfc_flags             = pfc_flags;
385         r.drep[0]               = DCERPC_DREP_LE;
386         r.drep[1]               = 0;
387         r.drep[2]               = 0;
388         r.drep[3]               = 0;
389         r.auth_length           = auth_length;
390         r.call_id               = call_id;
391         r.u                     = *u;
392
393         status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
394         if (!NT_STATUS_IS_OK(status)) {
395                 return status;
396         }
397
398         if (DEBUGLEVEL >= 10) {
399                 /* set frag len for print function */
400                 r.frag_length = blob->length;
401                 NDR_PRINT_DEBUG(ncacn_packet, &r);
402         }
403
404         return NT_STATUS_OK;
405 }
406
407 #define DCERPC_PAYLOAD_PADDING_SIZE 16 //TODO???
408
409 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
410                                  enum dcerpc_AuthType auth_type,
411                                  enum dcerpc_AuthLevel auth_level,
412                                  uint8_t auth_pad_length,
413                                  uint32_t auth_context_id,
414                                  const DATA_BLOB *credentials,
415                                  DATA_BLOB *blob)
416 {
417         struct dcerpc_auth r;
418         enum ndr_err_code ndr_err;
419
420         r.auth_type             = auth_type;
421         r.auth_level            = auth_level;
422         r.auth_pad_length       = auth_pad_length;
423         r.auth_reserved         = 0;
424         r.auth_context_id       = auth_context_id;
425         r.credentials           = *credentials;
426
427         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
428                 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
429         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
430                 return ndr_map_error2ntstatus(ndr_err);
431         }
432
433         if (DEBUGLEVEL >= 10) {
434                 NDR_PRINT_DEBUG(dcerpc_auth, &r);
435         }
436
437         return NT_STATUS_OK;
438 }
439
440 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
441                                           size_t pad_len,
442                                           DATA_BLOB *rpc_out)
443 {
444         char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
445         DATA_BLOB auth_info;
446         DATA_BLOB auth_blob;
447         uint16_t data_and_pad_len = 0;
448         NTSTATUS status;
449
450         if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
451                 return NT_STATUS_INVALID_PARAMETER_MIX;
452         }
453
454         if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
455             sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
456                 return NT_STATUS_OK;
457         }
458
459         if (sec->gensec == NULL) {
460                 return NT_STATUS_INVALID_PARAMETER_MIX;
461         }
462
463         if (pad_len) {
464                 /* Copy the sign/seal padding data. */
465                 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
466                         return NT_STATUS_NO_MEMORY;
467                 }
468         }
469
470         data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
471
472         /* marshall the dcerpc_auth with an actually empty auth_blob.
473          * This is needed because the ntmlssp signature includes the
474          * auth header. We will append the actual blob later. */
475         auth_blob = data_blob_null;
476         status = dcerpc_auth_blob(rpc_out->data,
477                                   sec->auth_type,
478                                   sec->auth_level,
479                                   pad_len,
480                                   sec->context_id,
481                                   &auth_blob,
482                                   &auth_info);
483         if (!NT_STATUS_IS_OK(status)) {
484                 return status;
485         }
486
487         /* append the header */
488         if (!data_blob_append(NULL, rpc_out,
489                                 auth_info.data, auth_info.length)) {
490                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
491                           (unsigned int)auth_info.length));
492                 return NT_STATUS_NO_MEMORY;
493         }
494         data_blob_free(&auth_info);
495
496         switch (sec->auth_level) {
497         case DCERPC_AUTH_LEVEL_PRIVACY:
498                 /* Data portion is encrypted. */
499                 status = gensec_seal_packet(sec->gensec,
500                                             rpc_out->data,
501                                             rpc_out->data
502                                             + DCERPC_RESPONSE_LENGTH,
503                                             data_and_pad_len,
504                                             rpc_out->data,
505                                             rpc_out->length,
506                                             &auth_blob);
507                 if (!NT_STATUS_IS_OK(status)) {
508                         return status;
509                 }
510                 break;
511
512         case DCERPC_AUTH_LEVEL_INTEGRITY:
513                 /* Data is signed. */
514                 status = gensec_sign_packet(sec->gensec,
515                                             rpc_out->data,
516                                             rpc_out->data
517                                             + DCERPC_RESPONSE_LENGTH,
518                                             data_and_pad_len,
519                                             rpc_out->data,
520                                             rpc_out->length,
521                                             &auth_blob);
522                 if (!NT_STATUS_IS_OK(status)) {
523                         return status;
524                 }
525                 break;
526
527         default:
528                 /* Can't happen. */
529                 smb_panic("bad auth level");
530                 /* Notreached. */
531                 return NT_STATUS_INVALID_PARAMETER;
532         }
533
534         /* Finally attach the blob. */
535         if (!data_blob_append(NULL, rpc_out,
536                                 auth_blob.data, auth_blob.length)) {
537                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
538                           (unsigned int)auth_blob.length));
539                 return NT_STATUS_NO_MEMORY;
540         }
541         data_blob_free(&auth_blob);
542
543         return NT_STATUS_OK;
544 }
545
546 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
547                            struct ncacn_packet *pkt,
548                            DATA_BLOB *pkt_trailer,
549                            size_t header_size,
550                            DATA_BLOB *raw_pkt,
551                            size_t *pad_len)
552 {
553         NTSTATUS status;
554         struct dcerpc_auth auth_info;
555         uint32_t auth_length;
556         DATA_BLOB full_pkt;
557         DATA_BLOB data;
558
559         switch (sec->auth_level) {
560         case DCERPC_AUTH_LEVEL_PRIVACY:
561                 DEBUG(10, ("Requested Privacy.\n"));
562                 break;
563
564         case DCERPC_AUTH_LEVEL_INTEGRITY:
565                 DEBUG(10, ("Requested Integrity.\n"));
566                 break;
567
568         case DCERPC_AUTH_LEVEL_CONNECT:
569                 if (pkt->auth_length != 0) {
570                         break;
571                 }
572                 *pad_len = 0;
573                 return NT_STATUS_OK;
574
575         case DCERPC_AUTH_LEVEL_NONE:
576                 if (pkt->auth_length != 0) {
577                         DEBUG(3, ("Got non-zero auth len on non "
578                                   "authenticated connection!\n"));
579                         return NT_STATUS_INVALID_PARAMETER;
580                 }
581                 *pad_len = 0;
582                 return NT_STATUS_OK;
583
584         default:
585                 DEBUG(3, ("Unimplemented Auth Level %d",
586                           sec->auth_level));
587                 return NT_STATUS_INVALID_PARAMETER;
588         }
589
590         /* Paranioa checks for auth_length. */
591         if (pkt->auth_length > pkt->frag_length) {
592                 return NT_STATUS_INFO_LENGTH_MISMATCH;
593         }
594         if (((unsigned int)pkt->auth_length
595              + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
596             ((unsigned int)pkt->auth_length
597              + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
598                 /* Integer wrap attempt. */
599                 return NT_STATUS_INFO_LENGTH_MISMATCH;
600         }
601
602         status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
603                                           &auth_info, &auth_length, false);
604         if (!NT_STATUS_IS_OK(status)) {
605                 return status;
606         }
607
608         data = data_blob_const(raw_pkt->data + header_size,
609                                 pkt_trailer->length - auth_length);
610         full_pkt = data_blob_const(raw_pkt->data,
611                                 raw_pkt->length - auth_info.credentials.length);
612
613         switch (sec->auth_type) {
614         case DCERPC_AUTH_TYPE_NONE:
615         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
616                 return NT_STATUS_OK;
617         default:
618                 break;
619         }
620
621         switch (sec->auth_level) {
622         case DCERPC_AUTH_LEVEL_PRIVACY:
623                 /* Data portion is encrypted. */
624                 status = gensec_unseal_packet(sec->gensec,
625                                             data.data,
626                                             data.length,
627                                             full_pkt.data,
628                                             full_pkt.length,
629                                             &auth_info.credentials);
630                 break;
631
632         case DCERPC_AUTH_LEVEL_INTEGRITY:
633                 /* Data is signed. */
634                 status = gensec_check_packet(sec->gensec,
635                                             data.data,
636                                             data.length,
637                                             full_pkt.data,
638                                             full_pkt.length,
639                                             &auth_info.credentials);
640                 break;
641         default:
642                 return NT_STATUS_INVALID_PARAMETER;
643         }
644         /* TODO: remove later
645          * this is still needed because in the server code the
646          * pkt_trailer actually has a copy of the raw data, and they
647          * are still both used in later calls */
648         if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
649                 memcpy(pkt_trailer->data, data.data, data.length);
650         }
651
652         *pad_len = auth_info.auth_pad_length;
653         data_blob_free(&auth_info.credentials);
654         return NT_STATUS_OK;
655 }
656
657 static void dcerpc_connection_loop(struct tevent_req *subreq);
658
659 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
660                                                struct tevent_context *ev)
661 {
662         if (ev == NULL) {
663                 return NT_STATUS_INVALID_PARAMETER; // TODO...
664         }
665
666         if (conn->loop.subreq) {
667                 if (conn->loop.ev != ev) {
668                         return NT_STATUS_INVALID_PARAMETER; // TODO...
669                 }
670                 return NT_STATUS_OK;
671         }
672
673         if (conn->calls.list == NULL) {
674                 conn->loop.ev = NULL;
675                 return NT_STATUS_OK;
676         }
677
678         conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
679                                                           ev,
680                                                           conn->transport.stream);
681         if (conn->loop.subreq == NULL) {
682                 return NT_STATUS_NO_MEMORY;
683         }
684         tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
685         conn->loop.ev = ev;
686         return NT_STATUS_OK;
687 }
688
689 static void dcerpc_connection_loop(struct tevent_req *subreq)
690 {
691         struct dcerpc_connection *conn =
692                 tevent_req_callback_data(subreq,
693                 struct dcerpc_connection);
694         NTSTATUS error;
695         struct ncacn_packet *pkt;
696         DATA_BLOB pdu;
697         struct dcerpc_call *call;
698         bool valid_type = false;
699         bool allow_fragments = false;
700
701         conn->loop.subreq = NULL;
702
703         error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
704         if (!NT_STATUS_IS_OK(error)) {
705                 TALLOC_FREE(subreq);
706                 // disconnect and notify pending calls
707                 return;
708         }
709
710         if (DEBUGLEVEL >= 10) {
711                 NDR_PRINT_DEBUG(ncacn_packet, pkt);
712         }
713
714         switch (pkt->ptype) {
715         case DCERPC_PKT_REQUEST:
716                 /* Ordinary request. */
717                 valid_type = true;
718                 allow_fragments = true;
719                 break;
720
721         case DCERPC_PKT_PING:
722                 /* Connectionless is server alive ? */
723                 break;
724
725         case DCERPC_PKT_RESPONSE:
726                 /* Ordinary reply. */
727                 valid_type = true;
728                 allow_fragments = true;
729                 break;
730
731         case DCERPC_PKT_FAULT:
732                 /* Fault in processing of call. */
733                 valid_type = true;
734                 break;
735
736         case DCERPC_PKT_WORKING:
737                 /* Connectionless reply to a ping when server busy. */
738                 break;
739
740         case DCERPC_PKT_NOCALL:
741                 /* Connectionless reply to a ping when server has lost part of clients call. */
742                 break;
743
744         case DCERPC_PKT_REJECT:
745                 /* Refuse a request with a code. */
746                 break;
747
748         case DCERPC_PKT_ACK:
749                 break;
750
751         case DCERPC_PKT_CL_CANCEL:
752                 break;
753
754         case DCERPC_PKT_FACK:
755                 break;
756
757         case DCERPC_PKT_CANCEL_ACK:
758                 /* Server ACK to client cancel request. */
759                 break;
760
761         case DCERPC_PKT_BIND:
762                 /* Bind to interface. */
763                 valid_type = true;
764                 break;
765
766         case DCERPC_PKT_BIND_ACK:
767                 /* Server ack of bind. */
768                 valid_type = true;
769                 break;
770
771         case DCERPC_PKT_BIND_NAK:
772                 /* Server nack of bind. */
773                 valid_type = true;
774                 break;
775
776         case DCERPC_PKT_ALTER:
777                 /* Alter auth. */
778                 valid_type = true;
779                 break;
780
781         case DCERPC_PKT_ALTER_RESP:
782                 /* Reply to alter auth. */
783                 valid_type = true;
784                 break;
785
786         case DCERPC_PKT_AUTH3:
787                 /* not the real name!  this is undocumented! */
788                 valid_type = true;
789                 break;
790
791         case DCERPC_PKT_SHUTDOWN:
792                 /* Server to client request to shutdown. */
793                 valid_type = true;
794                 break;
795
796         case DCERPC_PKT_CO_CANCEL:
797                 /* Connection-oriented cancel request. */
798                 valid_type = true;
799                 break;
800
801         case DCERPC_PKT_ORPHANED:
802                 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
803                 valid_type = true;
804                 break;
805
806         case DCERPC_PKT_RTS:
807                 /* RTS packets used in ncacn_http */
808                 break;
809         }
810
811         if (!valid_type) {
812                 TALLOC_FREE(subreq);
813                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
814                 return;
815         }
816
817         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
818                 if (!allow_fragments) {
819                         TALLOC_FREE(subreq);
820                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
821                         return;
822                 }
823         }
824
825         if (conn->calls.active != NULL) {
826
827                 if (pkt->call_id != conn->calls.active->call_id) {
828                         TALLOC_FREE(subreq);
829                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
830                         return;
831                 }
832
833                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
834                         TALLOC_FREE(subreq);
835                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
836                         return;
837                 }
838
839                 call = conn->calls.active;
840
841                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
842                         conn->calls.active = NULL;
843                 }
844         } else {
845                 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
846                         TALLOC_FREE(subreq);
847                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
848                         return;
849                 }
850
851                 call = conn->calls.list;
852         }
853
854         for (call = conn->calls.list; call; call = call->next) {
855                 if (call->call_id == pkt->call_id) {
856                         break;
857                 }
858         }
859
860         if (call == NULL) {
861                 call = conn->calls.new_call;
862         }
863
864         if (call == NULL) {
865                 TALLOC_FREE(subreq);
866                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
867                 return;
868         }
869
870         if (call->incoming.handler == NULL) {
871                 TALLOC_FREE(subreq);
872                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
873                 return;
874         }
875
876         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
877                 conn->calls.active = call;
878
879                 // TODO
880                 //
881                 // reassemble and return
882         }
883
884         error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
885         TALLOC_FREE(subreq);
886         if (!NT_STATUS_IS_OK(error)) {
887                 // disconnect and notify pending calls
888                 return;
889         }
890
891         if (conn->calls.new_call == NULL) {
892                 conn->loop.ev = NULL;
893                 return;
894         }
895
896         error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
897         if (!NT_STATUS_IS_OK(error)) {
898                 // disconnect and notify pending calls
899                 return;
900         }
901 }
902
903 struct dcerpc_do_bind_out_frag;
904
905 struct dcerpc_do_bind_state {
906         struct tevent_context *ev;
907         struct dcerpc_connection *conn;
908         struct dcerpc_call *call;
909         struct dcerpc_security *sec;
910         bool proposed_hdr_signing;
911         DATA_BLOB sec_in;
912         NTSTATUS sec_status;
913         DATA_BLOB sec_out;
914         struct dcerpc_do_bind_out_frag *out_frag;
915         uint32_t num_pres;
916         struct dcerpc_presentation **pres;
917         uint32_t remaining_pres;
918
919         uint32_t num_ctx;
920         struct dcerpc_ctx_list *ctx_list;
921         struct ndr_syntax_id features;
922 };
923
924 struct dcerpc_do_bind_out_frag {
925         struct tevent_context *ev;
926         struct dcerpc_connection *conn;
927         struct tevent_req *req;
928         enum dcerpc_pkt_type ptype;
929         DATA_BLOB blob;
930         struct iovec vector;
931         struct tevent_req *subreq_wait1;
932         struct tevent_req *subreq_wait2;
933 };
934
935 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
936                                    enum tevent_req_state req_state);
937
938 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
939 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
940
941 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
942                                               struct ncacn_packet *pkt,
943                                               DATA_BLOB frag);
944
945 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
946                                 struct tevent_context *ev,
947                                 struct dcerpc_connection *conn,
948                                 struct dcerpc_call *call,
949                                 struct dcerpc_security *sec,
950                                 uint32_t num_pres,
951                                 struct dcerpc_presentation **pres)
952 {
953         struct tevent_req *req;
954         struct dcerpc_do_bind_state *state;
955         struct tevent_req *subreq;
956
957         req = tevent_req_create(mem_ctx, &state,
958                                 struct dcerpc_do_bind_state);
959         if (req == NULL) {
960                 return NULL;
961         }
962         state->ev = ev;
963         state->conn = conn;
964         state->call = call;
965         state->sec = sec;
966         state->num_pres = num_pres;
967         state->pres = pres;
968
969         state->call->incoming.private_data = req;
970         state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
971         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
972
973         tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
974         tevent_req_defer_callback(req, ev);
975
976         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
977                 subreq = gensec_update_send(state, ev,
978                                             state->sec->gensec,
979                                             state->sec_in);
980                 if (tevent_req_nomem(subreq, req)) {
981                         return tevent_req_post(req, ev);
982                 }
983                 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
984
985                 return req;
986         }
987
988         state->sec_status = NT_STATUS_OK;
989
990         subreq = tevent_queue_wait_send(state, state->ev,
991                                         state->conn->calls.out_queue);
992         if (tevent_req_nomem(subreq, req)) {
993                 return tevent_req_post(req, ev);
994         }
995         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
996
997         return req;
998 }
999
1000 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1001                                    enum tevent_req_state req_state)
1002 {
1003         struct dcerpc_do_bind_state *state =
1004                 tevent_req_data(req,
1005                 struct dcerpc_do_bind_state);
1006
1007         if (state->out_frag != NULL) {
1008                 state->out_frag->req = NULL;
1009                 state->out_frag = NULL;
1010         }
1011
1012         if (state->call != NULL) {
1013                 ZERO_STRUCT(state->call->incoming);
1014                 DLIST_REMOVE(state->conn->calls.list, state->call);
1015                 state->call = NULL;
1016         }
1017 }
1018
1019 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1020 {
1021         struct tevent_req *req =
1022                 tevent_req_callback_data(subreq,
1023                 struct tevent_req);
1024         struct dcerpc_do_bind_state *state =
1025                 tevent_req_data(req,
1026                 struct dcerpc_do_bind_state);
1027         NTSTATUS status;
1028
1029         data_blob_free(&state->sec_out);
1030         status = gensec_update_recv(subreq, state, &state->sec_out);
1031         TALLOC_FREE(subreq);
1032         data_blob_free(&state->sec_in);
1033         state->sec_status = status;
1034         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1035                 status = NT_STATUS_OK;
1036         }
1037         if (!NT_STATUS_IS_OK(status)) {
1038                 tevent_req_nterror(req, status);
1039                 return;
1040         }
1041
1042         if (NT_STATUS_IS_OK(state->sec_status) &&
1043             state->sec_out.length == 0)
1044         {
1045                 tevent_req_done(req);
1046                 return;
1047         }
1048
1049         if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1050                 state->sec->client_hdr_signing =
1051                         gensec_have_feature(state->sec->gensec,
1052                                             GENSEC_FEATURE_SIGN_PKT_HEADER);
1053         }
1054
1055         subreq = tevent_queue_wait_send(state, state->ev,
1056                                         state->conn->calls.out_queue);
1057         if (tevent_req_nomem(subreq, req)) {
1058                 return;
1059         }
1060         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1061 }
1062
1063 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1064 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1065 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1066
1067 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1068 {
1069         struct tevent_req *req =
1070                 tevent_req_callback_data(subreq,
1071                 struct tevent_req);
1072         struct dcerpc_do_bind_state *state =
1073                 tevent_req_data(req,
1074                 struct dcerpc_do_bind_state);
1075         struct dcerpc_do_bind_out_frag *frag;
1076         size_t auth_len = 0;
1077         NTSTATUS status;
1078         DATA_BLOB auth_info = data_blob_null;
1079         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1080         union dcerpc_payload u;
1081         uint32_t i;
1082         bool require_ack = false;
1083         bool use_trans = true;
1084         bool ok;
1085
1086         ok = tevent_queue_wait_recv(subreq);
1087         if (!ok) {
1088                 //status = NT_STATUS_INTERNAL_ERROR;
1089                 tevent_req_oom(req);
1090                 return;
1091         }
1092         TALLOC_FREE(subreq);
1093
1094         /*
1095          * the fragment belongs to the connection instead of the request
1096          * because it has to remain in case the request is canceled
1097          */
1098         frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1099         if (tevent_req_nomem(frag, req)) {
1100                 return;
1101         }
1102         frag->ev = state->ev;
1103         frag->conn = state->conn;
1104         frag->req = req;
1105         state->out_frag = frag;
1106
1107         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1108                 if (state->sec->client_hdr_signing &&
1109                     !state->proposed_hdr_signing)
1110                 {
1111                         state->proposed_hdr_signing = true;
1112                         pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1113                         require_ack = true;
1114                 }
1115         }
1116
1117         //TODO : DCERPC_PFC_FLAG_CONC_MPX
1118
1119         //TODO: remaining_pres
1120
1121         if (!state->conn->features.bind_done) {
1122                 frag->ptype = DCERPC_PKT_BIND;
1123         } else if (require_ack) {
1124                 frag->ptype = DCERPC_PKT_ALTER;
1125         } else if (state->remaining_pres > 0) {
1126                 frag->ptype = DCERPC_PKT_ALTER;
1127         } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1128                 frag->ptype = DCERPC_PKT_ALTER;
1129         } else {
1130                 frag->ptype = DCERPC_PKT_AUTH3;
1131         }
1132
1133         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1134                 status = dcerpc_auth_blob(frag,
1135                                           state->sec->auth_type,
1136                                           state->sec->auth_level,
1137                                           0, /* auth_pad_length */
1138                                           state->sec->context_id, /* auth_context_id */
1139                                           &state->sec_out,
1140                                           &auth_info);
1141                 if (!NT_STATUS_IS_OK(status)) {
1142                         tevent_req_nterror(req, status);
1143                         return;
1144                 }
1145
1146                 auth_len = auth_info.length;
1147
1148                 if (auth_len) {
1149                         auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1150                 }
1151         }
1152
1153         state->num_ctx = state->num_pres;
1154         if (!state->conn->assoc->negotiate_done) {
1155                 state->num_ctx += 1;
1156         }
1157
1158         state->ctx_list = talloc_zero_array(frag,
1159                                             struct dcerpc_ctx_list,
1160                                             state->num_ctx);
1161         if (tevent_req_nomem(state->ctx_list, req)) {
1162                 return;
1163         }
1164
1165         for (i=0; i < state->num_pres; i++) {
1166                 state->ctx_list[i] = state->pres[i]->negotiate.req;
1167         }
1168
1169         if (!state->conn->assoc->negotiate_done) {
1170                 state->features = dcerpc_construct_bind_time_features(
1171                                         state->conn->assoc->client_features);
1172
1173                 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1174                 if (i > 0) {
1175                         state->ctx_list[i].abstract_syntax =
1176                                 state->ctx_list[i-1].abstract_syntax;
1177                 }
1178                 state->ctx_list[i].num_transfer_syntaxes = 1;
1179                 state->ctx_list[i].transfer_syntaxes = &state->features;
1180         }
1181
1182         switch (frag->ptype) {
1183         case DCERPC_PKT_BIND:
1184         case DCERPC_PKT_ALTER:
1185                 u.bind.max_xmit_frag    = state->conn->features.max_xmit_frag;
1186                 u.bind.max_recv_frag    = state->conn->features.max_recv_frag;
1187                 u.bind.assoc_group_id   = state->conn->assoc->assoc_group_id;
1188                 u.bind.num_contexts     = state->num_ctx;
1189                 u.bind.ctx_list         = state->ctx_list;
1190                 u.bind.auth_info        = auth_info;
1191                 break;
1192
1193         case DCERPC_PKT_AUTH3:
1194                 u.auth3._pad            = 0;
1195                 u.auth3.auth_info       = auth_info;
1196                 break;
1197         default:
1198                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1199                 return;
1200         }
1201
1202         status = dcerpc_ncacn_packet_blob(frag,
1203                                           frag->ptype,
1204                                           pfc_flags,
1205                                           auth_len,
1206                                           state->call->call_id,
1207                                           &u,
1208                                           &frag->blob);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1211                 tevent_req_nterror(req, status);
1212                 return;
1213         }
1214
1215         if (frag->ptype == DCERPC_PKT_AUTH3) {
1216                 use_trans = false;
1217         }
1218
1219         if (frag->conn->transport.use_trans_fn == NULL) {
1220                 use_trans = false;
1221         }
1222
1223         if (frag->conn->loop.subreq != NULL) {
1224                 use_trans = false;
1225         }
1226
1227         if (frag->conn->features.concurrent_multiplex) {
1228                 use_trans = false;
1229         }
1230
1231         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1232                 use_trans = false;
1233         }
1234
1235         if (use_trans) {
1236                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1237                                                 frag->ev,
1238                                                 frag->conn->transport.write_queue);
1239                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1240                         return;
1241                 }
1242                 tevent_req_set_callback(frag->subreq_wait1,
1243                                         dcerpc_do_bind_out_frag_trans_wait1,
1244                                         frag);
1245                 /*
1246                  * we need to block reads until our write is
1247                  * the next in the write queue.
1248                  */
1249                 frag->conn->loop.subreq = frag->subreq_wait1;
1250                 frag->conn->loop.ev = frag->ev;
1251         }
1252
1253         /*
1254          * We need to add a dcerpc_write_fragment_queue_send/recv()
1255          */
1256
1257         frag->vector.iov_base = frag->blob.data;
1258         frag->vector.iov_len = frag->blob.length;
1259         subreq = tstream_writev_queue_send(frag, frag->ev,
1260                                            frag->conn->transport.stream,
1261                                            frag->conn->transport.write_queue,
1262                                            &frag->vector, 1);
1263         if (tevent_req_nomem(subreq, req)) {
1264                 return;
1265         }
1266         tevent_req_set_callback(subreq,
1267                                 dcerpc_do_bind_out_frag_done,
1268                                 frag);
1269
1270         if (use_trans) {
1271                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1272                                                 frag->ev,
1273                                                 frag->conn->transport.write_queue);
1274                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1275                         return;
1276                 }
1277                 tevent_req_set_callback(frag->subreq_wait2,
1278                                         dcerpc_do_bind_out_frag_trans_wait2,
1279                                         frag);
1280         }
1281
1282         if (frag->ptype == DCERPC_PKT_AUTH3) {
1283                 return;
1284         }
1285
1286         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1287         if (tevent_req_nterror(req, status)) {
1288                 return;
1289         }
1290 }
1291
1292 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1293 {
1294         struct dcerpc_do_bind_out_frag *frag =
1295                 tevent_req_callback_data(subreq,
1296                 struct dcerpc_do_bind_out_frag);
1297         struct tevent_req *req = frag->req;
1298         NTSTATUS status;
1299         bool ok;
1300
1301         /*
1302          * TODO; what if the caller has been free'ed?
1303          */
1304
1305         frag->subreq_wait1 = NULL;
1306         frag->conn->loop.subreq = NULL;
1307
1308         ok = tevent_queue_wait_recv(subreq);
1309         if (!ok) {
1310                 status = NT_STATUS_INTERNAL_ERROR;
1311                 TALLOC_FREE(frag);
1312                 if (req) {
1313                         tevent_req_nterror(req, status);
1314                 }
1315                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1316                 return;
1317         }
1318
1319         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1320                 /*
1321                  * We added 3 entries into the queue,
1322                  * wait1, writev and wait2.
1323                  *
1324                  * There's more to write, we should not block
1325                  * further writev calls for a trans call.
1326                  *
1327                  * The wait2 stage will trigger the read.
1328                  */
1329                 TALLOC_FREE(subreq);
1330                 return;
1331         }
1332
1333         /*
1334          * we don't need wait2 anymore, we're sure that
1335          * we'll do a trans call.
1336          */
1337         TALLOC_FREE(frag->subreq_wait2);
1338
1339         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1340         if (!NT_STATUS_IS_OK(status)) {
1341                 TALLOC_FREE(frag);
1342                 if (req) {
1343                         tevent_req_nterror(req, status);
1344                 }
1345                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1346                 return;
1347         }
1348
1349         /* we free subreq after tstream_cli_np_use_trans */
1350         TALLOC_FREE(subreq);
1351
1352         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1353         if (!NT_STATUS_IS_OK(status)) {
1354                 TALLOC_FREE(frag);
1355                 if (req) {
1356                         tevent_req_nterror(req, status);
1357                 }
1358                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1359                 return;
1360         }
1361 }
1362
1363 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1364 {
1365         struct dcerpc_do_bind_out_frag *frag =
1366                 tevent_req_callback_data(subreq,
1367                 struct dcerpc_do_bind_out_frag);
1368         struct tevent_req *req = frag->req;
1369         NTSTATUS status;
1370         int ret;
1371         int sys_errno;
1372
1373         /*
1374          * If the caller has been free'ed, we have should
1375          * ignore any errors and just free 'frag'
1376          */
1377         if (req) {
1378                 struct dcerpc_do_bind_state *state =
1379                         tevent_req_data(req,
1380                         struct dcerpc_do_bind_state);
1381
1382                 state->out_frag = NULL;
1383         }
1384
1385         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1386         TALLOC_FREE(subreq);
1387         if (ret == -1) {
1388                 TALLOC_FREE(frag);
1389                 status = map_nt_error_from_unix_common(sys_errno);
1390                 if (req) {
1391                         tevent_req_nterror(req, status);
1392                 }
1393                 return;
1394         }
1395
1396         if (frag->ptype == DCERPC_PKT_AUTH3) {
1397                 TALLOC_FREE(frag);
1398                 if (req == NULL) {
1399                         return;
1400                 }
1401                 tevent_req_done(req);
1402                 return;
1403         }
1404
1405         if (frag->subreq_wait2 != NULL) {
1406                 return;
1407         }
1408
1409         TALLOC_FREE(frag);
1410
1411         /* we need to wait for incoming pdus */
1412 }
1413
1414 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1415 {
1416         struct dcerpc_do_bind_out_frag *frag =
1417                 tevent_req_callback_data(subreq,
1418                 struct dcerpc_do_bind_out_frag);
1419         struct tevent_req *req = frag->req;
1420         NTSTATUS status;
1421         bool ok;
1422
1423         frag->subreq_wait2 = NULL;
1424
1425         ok = tevent_queue_wait_recv(subreq);
1426         if (!ok) {
1427                 status = NT_STATUS_INTERNAL_ERROR;
1428                 TALLOC_FREE(frag);
1429                 if (req) {
1430                         tevent_req_nterror(req, status);
1431                 }
1432                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1433                 return;
1434         }
1435
1436         TALLOC_FREE(subreq);
1437
1438         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1439         if (!NT_STATUS_IS_OK(status)) {
1440                 TALLOC_FREE(frag);
1441                 if (req) {
1442                         tevent_req_nterror(req, status);
1443                 }
1444                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1445                 return;
1446         }
1447
1448         TALLOC_FREE(frag);
1449
1450         /* we need to wait for incoming pdus */
1451 }
1452
1453 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
1454                                                  struct ncacn_packet *pkt,
1455                                                  DATA_BLOB frag)
1456 {
1457         struct tevent_req *req =
1458                 talloc_get_type_abort(private_data,
1459                 struct tevent_req);
1460         struct dcerpc_do_bind_state *state =
1461                 tevent_req_data(req,
1462                 struct dcerpc_do_bind_state);
1463         NTSTATUS status;
1464         size_t i;
1465
1466         /* Ensure we have the correct type. */
1467         switch (pkt->ptype) {
1468         case DCERPC_PKT_BIND_ACK:
1469         case DCERPC_PKT_ALTER_RESP:
1470                 if (!state->conn->features.bind_done) {
1471                         if (pkt->u.bind_ack.max_recv_frag < 1234) {
1472                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1473                         }
1474                         if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1475                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1476                         }
1477                         state->conn->features.max_recv_frag =
1478                                 pkt->u.bind_ack.max_recv_frag;
1479                         state->conn->features.max_xmit_frag =
1480                                 pkt->u.bind_ack.max_xmit_frag;
1481
1482                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1483                                 state->conn->features.concurrent_multiplex = true;
1484                         }
1485
1486                         state->conn->features.bind_done = true;
1487                 }
1488
1489                 if (!state->conn->assoc->negotiate_done) {
1490                         state->conn->assoc->negotiate_done = true;
1491                         state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1492                 }
1493
1494                 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1495                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1496                 }
1497
1498                 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1499                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1500                 }
1501
1502                 if (state->proposed_hdr_signing) {
1503                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1504                                 state->sec->hdr_signing = true;
1505                         }
1506                 }
1507
1508                 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1509                         struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1510
1511                         if (i < state->num_pres) {
1512                                 state->pres[i]->negotiate.ack = *ack;
1513                                 continue;
1514                         }
1515
1516                         if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1517                                 continue;
1518                         }
1519
1520                         state->conn->assoc->features = state->conn->assoc->client_features;
1521                         state->conn->assoc->features &= ack->reason.negotiate;
1522                 }
1523
1524                 for (i = 0; i < state->num_pres; i++) {
1525                         struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1526                         bool ok;
1527
1528                         if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1529                                 continue;
1530                         }
1531
1532                         ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1533                                                  &ack->syntax);
1534                         if (!ok) {
1535                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1536                         }
1537                 }
1538
1539                 if (pkt->auth_length >= 8) {
1540                         struct tevent_req *subreq;
1541
1542                         state->sec_in = data_blob_talloc(state,
1543                                         pkt->u.bind_ack.auth_info.data + 8,
1544                                         pkt->u.bind_ack.auth_info.length - 8);
1545
1546                         subreq = gensec_update_send(state, state->ev,
1547                                                     state->sec->gensec,
1548                                                     state->sec_in);
1549                         if (tevent_req_nomem(subreq, req)) {
1550                                 return NT_STATUS_OK;
1551                         }
1552                         tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1553                         return NT_STATUS_OK;
1554                 }
1555
1556                 tevent_req_done(req);
1557                 return NT_STATUS_OK;
1558
1559         //case DCERPC_PKT_ALTER_RESP:
1560                 if (pkt->auth_length != 0) {
1561                         return NT_STATUS_NOT_IMPLEMENTED;
1562                 }
1563
1564                 return NT_STATUS_NOT_IMPLEMENTED;
1565 //TODO
1566 #if 0
1567                 /* Point the return values at the NDR data. */
1568                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1569
1570                 if (pkt->auth_length) {
1571                         /* We've already done integer wrap tests in
1572                          * dcerpc_check_auth(). */
1573                         payload.length = frag.length
1574                                          - DCERPC_RESPONSE_LENGTH
1575                                          - pad_len
1576                                          - DCERPC_AUTH_TRAILER_LENGTH
1577                                          - pkt->auth_length;
1578                 } else {
1579                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1580                 }
1581
1582                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1583                         if (pkt->drep[0] & DCERPC_DREP_LE) {
1584                                 state->response.bigendian = false;
1585                         } else {
1586                                 state->response.bigendian = true;
1587                         }
1588                 }
1589
1590                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1591                            (long unsigned int)frag.length,
1592                            (long unsigned int)payload.length,
1593                            (unsigned int)pad_len));
1594
1595                 /*
1596                  * If this is the first reply, and the allocation hint is
1597                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
1598                  * correct size.
1599                  */
1600
1601                 if ((state->response.blob.length == 0) &&
1602                     pkt->u.response.alloc_hint &&
1603                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
1604                         ok = data_blob_realloc(state, &state->response.blob,
1605                                                pkt->u.response.alloc_hint);
1606                         if (!ok) {
1607                                 DEBUG(0, ("reply alloc hint %d too "
1608                                           "large to allocate\n",
1609                                     (int)pkt->u.response.alloc_hint));
1610                                 return NT_STATUS_NO_MEMORY;
1611                         }
1612                 }
1613
1614                 new_total = state->response.ofs + payload.length;
1615
1616                 if (new_total > 15 * 1024 *1024) {
1617                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1618                 }
1619
1620                 missing = new_total - state->response.blob.length;
1621
1622                 if (missing > 0) {
1623                         ok = data_blob_realloc(state, &state->response.blob,
1624                                                new_total);
1625                         if (!ok) {
1626                                 DEBUG(0, ("reply alloc hint %d too "
1627                                           "large to allocate\n",
1628                                     (int)pkt->u.response.alloc_hint));
1629                                 return NT_STATUS_NO_MEMORY;
1630                         }
1631                 }
1632
1633                 memcpy(state->response.blob.data + state->response.ofs,
1634                        payload.data, payload.length);
1635                 state->response.ofs += payload.length;
1636
1637                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1638                         tevent_req_done(req);//TODO
1639                         return NT_STATUS_OK;
1640                 }
1641                 return NT_STATUS_OK;
1642 #endif
1643                 return NT_STATUS_NOT_IMPLEMENTED;
1644
1645         case DCERPC_PKT_FAULT:
1646
1647                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1648                           "code %s received from %s!\n",
1649                           dcerpc_errstr(talloc_tos(),
1650                           pkt->u.fault.status),
1651                           "TODO"));
1652
1653                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1654                 if (NT_STATUS_IS_OK(status)) {
1655                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
1656                 }
1657
1658                 tevent_req_nterror(req, status);//TODO
1659                 return NT_STATUS_OK;
1660         default:
1661                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1662                           (unsigned int)pkt->ptype,
1663                          "TODO"));
1664                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1665         }
1666
1667         return NT_STATUS_RPC_PROTOCOL_ERROR;
1668 }
1669
1670 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1671 {
1672         struct dcerpc_do_bind_state *state =
1673                 tevent_req_data(req,
1674                 struct dcerpc_do_bind_state);
1675         NTSTATUS status;
1676
1677         if (tevent_req_is_nterror(req, &status)) {
1678                 tevent_req_received(req);
1679                 return status;
1680         }
1681
1682         if (!NT_STATUS_IS_OK(state->sec_status)) {
1683                 status = state->sec_status;
1684                 tevent_req_received(req);
1685                 return status;
1686         }
1687
1688         tevent_req_received(req);
1689         return NT_STATUS_OK;
1690 }
1691
1692 struct dcerpc_do_request_out_frag;
1693
1694 struct dcerpc_do_request_state {
1695         struct tevent_context *ev;
1696         struct dcerpc_connection *conn;
1697         struct dcerpc_call *call;
1698         const struct GUID *object;
1699         uint16_t opnum;
1700         struct {
1701                 const DATA_BLOB *blob;
1702                 size_t ofs;
1703                 bool bigendian;
1704                 DATA_BLOB trailer;
1705                 size_t trailer_ofs;
1706         } request;
1707         bool verify_bitmask1;
1708         bool verify_pcontext;
1709         bool got_first;
1710         struct dcerpc_do_request_out_frag *out_frag;
1711         struct {
1712                 DATA_BLOB blob;
1713                 size_t ofs;
1714                 bool bigendian;
1715         } response;
1716 };
1717
1718 struct dcerpc_do_request_out_frag {
1719         struct tevent_context *ev;
1720         struct dcerpc_connection *conn;
1721         struct tevent_req *req;
1722         DATA_BLOB blob;
1723         bool is_last;
1724         struct iovec vector;
1725         struct tevent_req *subreq_wait1;
1726         struct tevent_req *subreq_wait2;
1727 };
1728
1729 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1730                                       enum tevent_req_state req_state);
1731
1732 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1733 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1734                                             void *private_data);
1735
1736 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
1737                                                  struct ncacn_packet *pkt,
1738                                                  DATA_BLOB frag);
1739
1740 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1741                                 struct tevent_context *ev,
1742                                 struct dcerpc_connection *conn,
1743                                 struct dcerpc_call *call,
1744                                 const struct GUID *object,
1745                                 uint16_t opnum,
1746                                 const DATA_BLOB *request,
1747                                 bool bigendian)
1748 {
1749         struct tevent_req *req;
1750         struct dcerpc_do_request_state *state;
1751         bool ok;
1752
1753         req = tevent_req_create(mem_ctx, &state,
1754                                 struct dcerpc_do_request_state);
1755         if (req == NULL) {
1756                 return NULL;
1757         }
1758         state->ev = ev;
1759         state->conn = conn;
1760         state->call = call;
1761         state->object = object;
1762         state->opnum = opnum;
1763         state->request.blob = request;
1764         state->request.bigendian = bigendian;
1765
1766         dcerpc_do_request_verification_trailer(req);
1767         if (!tevent_req_is_in_progress(req)) {
1768                 return tevent_req_post(req, ev);
1769         }
1770
1771         state->call->incoming.private_data = req;
1772         state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1773         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1774
1775         tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1776         tevent_req_defer_callback(req, ev);
1777
1778         ok = tevent_queue_add(state->conn->calls.out_queue,
1779                               state->ev,
1780                               req,
1781                               dcerpc_do_request_out_frag_next,
1782                               NULL);
1783         if (!ok) {
1784                 tevent_req_nomem(NULL, req);
1785                 return tevent_req_post(req, ev);
1786         }
1787
1788         return req;
1789 }
1790
1791 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1792                                       enum tevent_req_state req_state)
1793 {
1794         struct dcerpc_do_request_state *state =
1795                 tevent_req_data(req,
1796                 struct dcerpc_do_request_state);
1797
1798         if (state->out_frag != NULL) {
1799                 state->out_frag->req = NULL;
1800                 state->out_frag = NULL;
1801         }
1802
1803         if (state->call != NULL) {
1804                 if (state->call == state->conn->calls.active) {
1805                         state->conn->calls.active = NULL;
1806                 }
1807                 ZERO_STRUCT(state->call->incoming);
1808                 DLIST_REMOVE(state->conn->calls.list, state->call);
1809                 state->call = NULL;
1810         }
1811 }
1812
1813 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1814 {
1815         struct dcerpc_do_request_state *state =
1816                 tevent_req_data(req,
1817                 struct dcerpc_do_request_state);
1818         struct dcerpc_sec_verification_trailer *t;
1819         struct dcerpc_sec_vt *c = NULL;
1820         struct ndr_push *ndr = NULL;
1821         enum ndr_err_code ndr_err;
1822         size_t align = 0;
1823         size_t pad = 0;
1824
1825         if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1826                 return;
1827         }
1828
1829         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1830         if (tevent_req_nomem(t, req)) {
1831                 return;
1832         }
1833
1834         if (!state->call->sec->verified_bitmask1) {
1835                 t->commands = talloc_realloc(t, t->commands,
1836                                              struct dcerpc_sec_vt,
1837                                              t->count.count + 1);
1838                 if (tevent_req_nomem(t->commands, req)) {
1839                         return;
1840                 }
1841                 c = &t->commands[t->count.count++];
1842                 ZERO_STRUCTP(c);
1843
1844                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1845                 if (state->call->sec->client_hdr_signing) {
1846                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1847                 }
1848                 state->verify_bitmask1 = true;
1849         }
1850
1851         if (!state->call->pres->verified_pcontext) {
1852                 t->commands = talloc_realloc(t, t->commands,
1853                                              struct dcerpc_sec_vt,
1854                                              t->count.count + 1);
1855                 if (tevent_req_nomem(t->commands, req)) {
1856                         return;
1857                 }
1858                 c = &t->commands[t->count.count++];
1859                 ZERO_STRUCTP(c);
1860
1861                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1862                 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1863                 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1864
1865                 state->verify_pcontext = true;
1866         }
1867
1868         if (!state->call->sec->hdr_signing) {
1869                 t->commands = talloc_realloc(t, t->commands,
1870                                              struct dcerpc_sec_vt,
1871                                              t->count.count + 1);
1872                 if (tevent_req_nomem(t->commands, req)) {
1873                         return;
1874                 }
1875                 c = &t->commands[t->count.count++];
1876                 ZERO_STRUCTP(c);
1877
1878                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1879                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1880                 if (state->request.bigendian) {
1881                         c->u.header2.drep[0] = 0;
1882                 } else {
1883                         c->u.header2.drep[0] = DCERPC_DREP_LE;
1884                 }
1885                 c->u.header2.drep[1] = 0;
1886                 c->u.header2.drep[2] = 0;
1887                 c->u.header2.drep[3] = 0;
1888                 c->u.header2.call_id = state->call->call_id;
1889                 c->u.header2.context_id = 0;
1890                 c->u.header2.opnum = state->opnum;
1891         }
1892
1893         if (t->count.count == 0) {
1894                 TALLOC_FREE(t);
1895                 return;
1896         }
1897
1898         c = &t->commands[t->count.count - 1];
1899         c->command |= DCERPC_SEC_VT_COMMAND_END;
1900
1901         if (DEBUGLEVEL >= 10) {
1902                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1903         }
1904
1905         ndr = ndr_push_init_ctx(state);
1906         if (tevent_req_nomem(ndr, req)) {
1907                 return;
1908         }
1909
1910         //TODO if (state->request.bigendian)
1911
1912         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1913                                                 NDR_SCALARS | NDR_BUFFERS,
1914                                                 t);
1915         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1916                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1917                 tevent_req_nterror(req, status);
1918                 return;
1919         }
1920         state->request.trailer = ndr_push_blob(ndr);
1921
1922         align = state->request.blob->length & 0x3;
1923         if (align > 0) {
1924                 pad = 4 - align;
1925         }
1926         if (pad > 0) {
1927                 bool ok;
1928                 uint8_t *p;
1929                 const uint8_t zeros[4] = { 0, };
1930
1931                 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
1932                 if (!ok) {
1933                         tevent_req_oom(req);
1934                         return;
1935                 }
1936
1937                 /* move the padding to the start */
1938                 p = state->request.trailer.data;
1939                 memmove(p + pad, p, state->request.trailer.length - pad);
1940                 memset(p, 0, pad);
1941         }
1942
1943         return;
1944 }
1945
1946 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
1947 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
1948 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
1949
1950 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1951                                             void *private_data)
1952 {
1953         struct dcerpc_do_request_state *state =
1954                 tevent_req_data(req,
1955                 struct dcerpc_do_request_state);
1956         struct dcerpc_do_request_out_frag *frag;
1957         size_t hdr_len = DCERPC_REQUEST_LENGTH;
1958         size_t auth_len;
1959         size_t frag_len;
1960         uint8_t flags = 0;
1961         size_t pad_len;
1962         size_t data_left;
1963         size_t data_thistime;
1964         size_t trailer_left;
1965         size_t trailer_thistime = 0;
1966         size_t total_left;
1967         size_t total_thistime;
1968         NTSTATUS status;
1969         union dcerpc_payload u;
1970         bool ok;
1971         struct tevent_req *subreq;
1972         bool use_trans = true;
1973
1974         if (state->object) {
1975                 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1976                 hdr_len += 16;
1977         }
1978
1979         /*
1980          * the fragment belongs to the connection instead of the request
1981          * because it has to remain in case the request is canceled
1982          */
1983         frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
1984         if (tevent_req_nomem(frag, req)) {
1985                 return;
1986         }
1987         frag->ev = state->ev;
1988         frag->conn = state->conn;
1989         frag->req = req;
1990         state->out_frag = frag;
1991
1992         data_left = state->request.blob->length - state->request.ofs;
1993         trailer_left = state->request.trailer.length - state->request.trailer_ofs;
1994         total_left = data_left + trailer_left;
1995         if (total_left < data_left || total_left < trailer_left) {
1996                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1997                 return;
1998         }
1999
2000         status = dcerpc_guess_pdu_sizes(state->call->sec,
2001                                     hdr_len, total_left,
2002                                     state->conn->features.max_xmit_frag,
2003                                     16,//TODO
2004                                     &total_thistime,
2005                                     &frag_len, &auth_len, &pad_len);
2006         if (!NT_STATUS_IS_OK(status)) {
2007                 tevent_req_nterror(req, status);
2008                 return;
2009         }
2010
2011         if (state->request.ofs == 0) {
2012                 flags |= DCERPC_PFC_FLAG_FIRST;
2013         }
2014
2015         if (total_thistime == total_left) {
2016                 flags |= DCERPC_PFC_FLAG_LAST;
2017         }
2018
2019         data_thistime = MIN(total_thistime, data_left);
2020         if (data_thistime < total_thistime) {
2021                 trailer_thistime = total_thistime - data_thistime;
2022         }
2023
2024         ZERO_STRUCT(u.request);
2025
2026         u.request.alloc_hint    = total_left;
2027         u.request.context_id    = state->call->pres->context_id;
2028         u.request.opnum         = state->opnum;
2029         if (state->object) {
2030                 u.request.object.object = *state->object;
2031         }
2032 //TODO pass state->request.bigendian
2033         status = dcerpc_ncacn_packet_blob(frag,
2034                                           DCERPC_PKT_REQUEST,
2035                                           flags,
2036                                           auth_len,
2037                                           state->call->call_id,
2038                                           &u,
2039                                           &frag->blob);
2040         if (!NT_STATUS_IS_OK(status)) {
2041                 tevent_req_nterror(req, status);
2042                 return;
2043         }
2044
2045         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2046          * compute it right for requests because the auth trailer is missing
2047          * at this stage */
2048         dcerpc_set_frag_length(&frag->blob, frag_len);
2049
2050         if (data_thistime > 0) {
2051                 const uint8_t *data_ptr;
2052
2053                 data_ptr = state->request.blob->data;
2054                 data_ptr += state->request.ofs;
2055
2056                 /* Copy in the data. */
2057                 ok = data_blob_append(frag, &frag->blob,
2058                                       data_ptr, data_thistime);
2059                 if (!ok) {
2060                         tevent_req_oom(req);
2061                         return;
2062                 }
2063
2064                 state->request.ofs += data_thistime;
2065         }
2066
2067         if (trailer_thistime > 0) {
2068                 const uint8_t *trailer_ptr;
2069
2070                 trailer_ptr = state->request.trailer.data;
2071                 trailer_ptr += state->request.trailer_ofs;
2072
2073                 /* Copy in the data. */
2074                 ok = data_blob_append(frag, &frag->blob,
2075                                       trailer_ptr, trailer_thistime);
2076                 if (!ok) {
2077                         tevent_req_oom(req);
2078                         return;
2079                 }
2080
2081                 state->request.trailer_ofs += trailer_thistime;
2082         }
2083
2084         switch (state->call->sec->auth_level) {
2085         case DCERPC_AUTH_LEVEL_NONE:
2086         case DCERPC_AUTH_LEVEL_CONNECT:
2087         case DCERPC_AUTH_LEVEL_PACKET:
2088                 break;
2089         case DCERPC_AUTH_LEVEL_INTEGRITY:
2090         case DCERPC_AUTH_LEVEL_PRIVACY:
2091                 status = dcerpc_response_auth_blob(state->call->sec,
2092                                                 pad_len,
2093                                                 &frag->blob);
2094                 if (!NT_STATUS_IS_OK(status)) {
2095                         tevent_req_nterror(req, status);
2096                         return;
2097                 }
2098                 break;
2099         default:
2100                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2101                 return;
2102         }
2103
2104         frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2105
2106         if (!frag->is_last) {
2107                 use_trans = false;
2108         }
2109
2110         if (frag->conn->transport.use_trans_fn == NULL) {
2111                 use_trans = false;
2112         }
2113
2114         if (frag->conn->loop.subreq != NULL) {
2115                 use_trans = false;
2116         }
2117
2118         if (frag->conn->features.concurrent_multiplex) {
2119                 use_trans = false;
2120         }
2121
2122         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2123                 use_trans = false;
2124         }
2125
2126         if (use_trans) {
2127                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2128                                                 frag->ev,
2129                                                 frag->conn->transport.write_queue);
2130                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2131                         return;
2132                 }
2133                 tevent_req_set_callback(frag->subreq_wait1,
2134                                         dcerpc_do_request_out_frag_trans_wait1,
2135                                         frag);
2136                 /*
2137                  * we need to block reads until our write is
2138                  * the next in the write queue.
2139                  */
2140                 frag->conn->loop.subreq = frag->subreq_wait1;
2141                 frag->conn->loop.ev = frag->ev;
2142         }
2143
2144         /*
2145          * We need to add a dcerpc_write_fragment_queue_send/recv()
2146          */
2147
2148         frag->vector.iov_base = frag->blob.data;
2149         frag->vector.iov_len = frag->blob.length;
2150         subreq = tstream_writev_queue_send(frag, frag->ev,
2151                                            frag->conn->transport.stream,
2152                                            frag->conn->transport.write_queue,
2153                                            &frag->vector, 1);
2154         if (tevent_req_nomem(subreq, req)) {
2155                 return;
2156         }
2157         tevent_req_set_callback(subreq,
2158                                 dcerpc_do_request_out_frag_done,
2159                                 frag);
2160
2161         if (use_trans) {
2162                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2163                                                 frag->ev,
2164                                                 frag->conn->transport.write_queue);
2165                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2166                         return;
2167                 }
2168                 tevent_req_set_callback(frag->subreq_wait2,
2169                                         dcerpc_do_request_out_frag_trans_wait2,
2170                                         frag);
2171         }
2172
2173         if (!frag->is_last) {
2174                 return;
2175         }
2176
2177         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2178         if (tevent_req_nterror(req, status)) {
2179                 return;
2180         }
2181 }
2182
2183 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2184 {
2185         struct dcerpc_do_request_out_frag *frag =
2186                 tevent_req_callback_data(subreq,
2187                 struct dcerpc_do_request_out_frag);
2188         struct tevent_req *req = frag->req;
2189         NTSTATUS status;
2190         bool ok;
2191
2192         /*
2193          * TODO; what if the caller has been free'ed?
2194          */
2195
2196         frag->subreq_wait1 = NULL;
2197         frag->conn->loop.subreq = NULL;
2198
2199         ok = tevent_queue_wait_recv(subreq);
2200         if (!ok) {
2201                 status = NT_STATUS_INTERNAL_ERROR;
2202                 TALLOC_FREE(frag);
2203                 if (req) {
2204                         tevent_req_nterror(req, status);
2205                 }
2206                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2207                 return;
2208         }
2209
2210         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2211                 /*
2212                  * We added 3 entries into the queue,
2213                  * wait1, writev and wait2.
2214                  *
2215                  * There's more to write, we should not block
2216                  * further writev calls for a trans call.
2217                  *
2218                  * The wait2 stage will trigger the read.
2219                  */
2220                 TALLOC_FREE(subreq);
2221                 return;
2222         }
2223
2224         /*
2225          * we don't need wait2 anymore, we're sure that
2226          * we'll do a trans call.
2227          */
2228         TALLOC_FREE(frag->subreq_wait2);
2229
2230         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2231         if (!NT_STATUS_IS_OK(status)) {
2232                 TALLOC_FREE(frag);
2233                 if (req) {
2234                         tevent_req_nterror(req, status);
2235                 }
2236                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2237                 return;
2238         }
2239
2240         /* we free subreq after tstream_cli_np_use_trans */
2241         TALLOC_FREE(subreq);
2242
2243         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2244         if (!NT_STATUS_IS_OK(status)) {
2245                 TALLOC_FREE(frag);
2246                 if (req) {
2247                         tevent_req_nterror(req, status);
2248                 }
2249                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2250                 return;
2251         }
2252 }
2253
2254 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2255 {
2256         struct dcerpc_do_request_out_frag *frag =
2257                 tevent_req_callback_data(subreq,
2258                 struct dcerpc_do_request_out_frag);
2259         struct tevent_req *req = frag->req;
2260         NTSTATUS status;
2261         int ret;
2262         int sys_errno;
2263
2264         /*
2265          * If the caller has been free'ed, we have should
2266          * ignore any errors and just free 'frag'
2267          */
2268         if (req) {
2269                 struct dcerpc_do_request_state *state =
2270                         tevent_req_data(req,
2271                         struct dcerpc_do_request_state);
2272
2273                 state->out_frag = NULL;
2274         }
2275
2276         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2277         TALLOC_FREE(subreq);
2278         if (ret == -1) {
2279                 TALLOC_FREE(frag);
2280                 status = map_nt_error_from_unix_common(sys_errno);
2281                 if (req) {
2282                         tevent_req_nterror(req, status);
2283                 }
2284                 return;
2285         }
2286
2287         if (frag->subreq_wait2 != NULL) {
2288                 return;
2289         }
2290
2291         if (frag->is_last) {
2292                 TALLOC_FREE(frag);
2293                 return;
2294         }
2295         TALLOC_FREE(frag);
2296
2297         if (req == NULL) {
2298                 return;
2299         }
2300
2301         dcerpc_do_request_out_frag_next(req, NULL);
2302 }
2303
2304 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2305 {
2306         struct dcerpc_do_request_out_frag *frag =
2307                 tevent_req_callback_data(subreq,
2308                 struct dcerpc_do_request_out_frag);
2309         struct tevent_req *req = frag->req;
2310         NTSTATUS status;
2311         bool ok;
2312
2313         frag->subreq_wait2 = NULL;
2314
2315         ok = tevent_queue_wait_recv(subreq);
2316         if (!ok) {
2317                 status = NT_STATUS_INTERNAL_ERROR;
2318                 TALLOC_FREE(frag);
2319                 if (req) {
2320                         tevent_req_nterror(req, status);
2321                 }
2322                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2323                 return;
2324         }
2325
2326         TALLOC_FREE(subreq);
2327
2328         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2329         if (!NT_STATUS_IS_OK(status)) {
2330                 TALLOC_FREE(frag);
2331                 if (req) {
2332                         tevent_req_nterror(req, status);
2333                 }
2334                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2335                 return;
2336         }
2337
2338         TALLOC_FREE(frag);
2339
2340         /* we need to wait for incoming pdus */
2341 }
2342
2343 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
2344                                                  struct ncacn_packet *pkt,
2345                                                  DATA_BLOB frag)
2346 {
2347         struct tevent_req *req =
2348                 talloc_get_type_abort(private_data,
2349                 struct tevent_req);
2350         struct dcerpc_do_request_state *state =
2351                 tevent_req_data(req,
2352                 struct dcerpc_do_request_state);
2353         NTSTATUS error;
2354         NTSTATUS status;
2355         size_t pad_len = 0;
2356         DATA_BLOB payload;
2357         size_t new_total;
2358         size_t missing;
2359         bool ok;
2360
2361         /* Ensure we have the correct type. */
2362         switch (pkt->ptype) {
2363         case DCERPC_PKT_RESPONSE:
2364
2365                 /* Here's where we deal with incoming sign/seal. */
2366                 error = dcerpc_check_pdu_auth(state->call->sec,
2367                                         pkt,
2368                                         &pkt->u.response.stub_and_verifier,
2369                                         DCERPC_RESPONSE_LENGTH,
2370                                         &frag, &pad_len);
2371                 if (!NT_STATUS_IS_OK(error)) {
2372                         return error;
2373                 }
2374
2375                 if (!state->got_first) {
2376                         state->got_first = true;
2377
2378                         if (pkt->drep[0] & DCERPC_DREP_LE) {
2379                                 state->response.bigendian = false;
2380                         } else {
2381                                 state->response.bigendian = true;
2382                         }
2383
2384                         if (state->verify_bitmask1) {
2385                                 state->call->sec->verified_bitmask1 = true;
2386                         }
2387
2388                         if (state->verify_pcontext) {
2389                                 state->call->pres->verified_pcontext = true;
2390                         }
2391                 }
2392
2393                 if (state->response.bigendian) {
2394                         if (pkt->drep[0] != 0) {
2395                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2396                         }
2397                 } else {
2398                         if (pkt->drep[0] != DCERPC_DREP_LE) {
2399                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2400                         }
2401                 }
2402                 if (pkt->drep[1] != 0) {
2403                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2404                 }
2405                 if (pkt->drep[2] != 0) {
2406                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2407                 }
2408                 if (pkt->drep[3] != 0) {
2409                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2410                 }
2411
2412                 if (pkt->u.response.context_id != state->call->pres->context_id) {
2413                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2414                 }
2415
2416                 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2417                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2418                 }
2419 //TODO
2420                 /* Point the return values at the NDR data. */
2421                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2422
2423                 if (pkt->auth_length) {
2424                         /* We've already done integer wrap tests in
2425                          * dcerpc_check_auth(). */
2426                         payload.length = frag.length
2427                                          - DCERPC_RESPONSE_LENGTH
2428                                          - pad_len
2429                                          - DCERPC_AUTH_TRAILER_LENGTH
2430                                          - pkt->auth_length;
2431                 } else {
2432                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2433                 }
2434
2435                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2436                            (long unsigned int)frag.length,
2437                            (long unsigned int)payload.length,
2438                            (unsigned int)pad_len));
2439
2440                 /*
2441                  * If this is the first reply, and the allocation hint is
2442                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
2443                  * correct size.
2444                  */
2445
2446                 if ((state->response.blob.length == 0) &&
2447                     pkt->u.response.alloc_hint &&
2448                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
2449                         ok = data_blob_realloc(state, &state->response.blob,
2450                                                pkt->u.response.alloc_hint);
2451                         if (!ok) {
2452                                 DEBUG(0, ("reply alloc hint %d too "
2453                                           "large to allocate\n",
2454                                     (int)pkt->u.response.alloc_hint));
2455                                 return NT_STATUS_NO_MEMORY;
2456                         }
2457                 }
2458
2459                 new_total = state->response.ofs + payload.length;
2460
2461                 if (new_total > 15 * 1024 *1024) {
2462                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2463                 }
2464
2465                 missing = new_total - state->response.blob.length;
2466
2467                 if (missing > 0) {
2468                         ok = data_blob_realloc(state, &state->response.blob,
2469                                                new_total);
2470                         if (!ok) {
2471                                 DEBUG(0, ("reply alloc hint %d too "
2472                                           "large to allocate\n",
2473                                     (int)pkt->u.response.alloc_hint));
2474                                 return NT_STATUS_NO_MEMORY;
2475                         }
2476                 }
2477
2478                 memcpy(state->response.blob.data + state->response.ofs,
2479                        payload.data, payload.length);
2480                 state->response.ofs += payload.length;
2481
2482                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2483                         tevent_req_done(req);//TODO
2484                         return NT_STATUS_OK;
2485                 }
2486
2487                 return dcerpc_connection_loop_restart(state->conn, state->ev);
2488
2489         case DCERPC_PKT_FAULT:
2490
2491                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2492                           "code %s received from %s!\n",
2493                           dcerpc_errstr(talloc_tos(),
2494                           pkt->u.fault.status),
2495                           "TODO"));
2496
2497                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2498                 if (NT_STATUS_IS_OK(status)) {
2499                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
2500                 }
2501
2502                 tevent_req_nterror(req, status);//TODO
2503                 return NT_STATUS_OK;
2504         default:
2505                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2506                           (unsigned int)pkt->ptype,
2507                          "TODO"));
2508                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2509         }
2510 }
2511
2512 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2513                                 TALLOC_CTX *mem_ctx,
2514                                 DATA_BLOB *response,
2515                                 bool *bigendian)
2516 {
2517         struct dcerpc_do_request_state *state =
2518                 tevent_req_data(req,
2519                 struct dcerpc_do_request_state);
2520         NTSTATUS status;
2521
2522         if (tevent_req_is_nterror(req, &status)) {
2523                 tevent_req_received(req);
2524                 return status;
2525         }
2526
2527         /* return data to caller and assign it ownership of memory */
2528         response->data = talloc_move(mem_ctx, &state->response.blob.data);
2529         response->length = state->response.blob.length;
2530         *bigendian = state->response.bigendian;
2531
2532         tevent_req_received(req);
2533         return NT_STATUS_OK;
2534 }