STEP01: dcerpc_check_pdu_auth fix librpc/rpc/dcerpc_connection.c
[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         if (auth_info.auth_type != sec->auth_type) {
609                 return NT_STATUS_RPC_PROTOCOL_ERROR;
610         }
611
612         if (auth_info.auth_level != sec->auth_level) {
613                 return NT_STATUS_RPC_PROTOCOL_ERROR;
614         }
615
616         if (auth_info.auth_context_id != sec->context_id) {
617                 return NT_STATUS_RPC_PROTOCOL_ERROR;
618         }
619
620         data = data_blob_const(raw_pkt->data + header_size,
621                                 pkt_trailer->length - auth_length);
622         full_pkt = data_blob_const(raw_pkt->data,
623                                 raw_pkt->length - auth_info.credentials.length);
624
625         switch (sec->auth_type) {
626         case DCERPC_AUTH_TYPE_NONE:
627         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
628                 return NT_STATUS_OK;
629         default:
630                 break;
631         }
632
633         switch (sec->auth_level) {
634         case DCERPC_AUTH_LEVEL_PRIVACY:
635                 /* Data portion is encrypted. */
636                 status = gensec_unseal_packet(sec->gensec,
637                                             data.data,
638                                             data.length,
639                                             full_pkt.data,
640                                             full_pkt.length,
641                                             &auth_info.credentials);
642                 if (!NT_STATUS_IS_OK(status)) {
643                         return status;
644                 }
645                 break;
646
647         case DCERPC_AUTH_LEVEL_INTEGRITY:
648                 /* Data is signed. */
649                 status = gensec_check_packet(sec->gensec,
650                                             data.data,
651                                             data.length,
652                                             full_pkt.data,
653                                             full_pkt.length,
654                                             &auth_info.credentials);
655                 if (!NT_STATUS_IS_OK(status)) {
656                         return status;
657                 }
658                 break;
659         default:
660                 return NT_STATUS_INVALID_PARAMETER;
661         }
662         /* TODO: remove later
663          * this is still needed because in the server code the
664          * pkt_trailer actually has a copy of the raw data, and they
665          * are still both used in later calls */
666         if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
667                 memcpy(pkt_trailer->data, data.data, data.length);
668         }
669
670         *pad_len = auth_info.auth_pad_length;
671         data_blob_free(&auth_info.credentials);
672         return NT_STATUS_OK;
673 }
674
675 static void dcerpc_connection_loop(struct tevent_req *subreq);
676
677 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
678                                                struct tevent_context *ev)
679 {
680         if (ev == NULL) {
681                 return NT_STATUS_INVALID_PARAMETER; // TODO...
682         }
683
684         if (conn->loop.subreq) {
685                 if (conn->loop.ev != ev) {
686                         return NT_STATUS_INVALID_PARAMETER; // TODO...
687                 }
688                 return NT_STATUS_OK;
689         }
690
691         if (conn->calls.list == NULL) {
692                 conn->loop.ev = NULL;
693                 return NT_STATUS_OK;
694         }
695
696         conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
697                                                           ev,
698                                                           conn->transport.stream);
699         if (conn->loop.subreq == NULL) {
700                 return NT_STATUS_NO_MEMORY;
701         }
702         tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
703         conn->loop.ev = ev;
704         return NT_STATUS_OK;
705 }
706
707 static void dcerpc_connection_loop(struct tevent_req *subreq)
708 {
709         struct dcerpc_connection *conn =
710                 tevent_req_callback_data(subreq,
711                 struct dcerpc_connection);
712         NTSTATUS error;
713         struct ncacn_packet *pkt;
714         DATA_BLOB pdu;
715         struct dcerpc_call *call;
716         bool valid_type = false;
717         bool allow_fragments = false;
718
719         conn->loop.subreq = NULL;
720
721         error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
722         if (!NT_STATUS_IS_OK(error)) {
723                 TALLOC_FREE(subreq);
724                 // disconnect and notify pending calls
725                 return;
726         }
727
728         if (DEBUGLEVEL >= 10) {
729                 NDR_PRINT_DEBUG(ncacn_packet, pkt);
730         }
731
732         switch (pkt->ptype) {
733         case DCERPC_PKT_REQUEST:
734                 /* Ordinary request. */
735                 valid_type = true;
736                 allow_fragments = true;
737                 break;
738
739         case DCERPC_PKT_PING:
740                 /* Connectionless is server alive ? */
741                 break;
742
743         case DCERPC_PKT_RESPONSE:
744                 /* Ordinary reply. */
745                 valid_type = true;
746                 allow_fragments = true;
747                 break;
748
749         case DCERPC_PKT_FAULT:
750                 /* Fault in processing of call. */
751                 valid_type = true;
752                 break;
753
754         case DCERPC_PKT_WORKING:
755                 /* Connectionless reply to a ping when server busy. */
756                 break;
757
758         case DCERPC_PKT_NOCALL:
759                 /* Connectionless reply to a ping when server has lost part of clients call. */
760                 break;
761
762         case DCERPC_PKT_REJECT:
763                 /* Refuse a request with a code. */
764                 break;
765
766         case DCERPC_PKT_ACK:
767                 break;
768
769         case DCERPC_PKT_CL_CANCEL:
770                 break;
771
772         case DCERPC_PKT_FACK:
773                 break;
774
775         case DCERPC_PKT_CANCEL_ACK:
776                 /* Server ACK to client cancel request. */
777                 break;
778
779         case DCERPC_PKT_BIND:
780                 /* Bind to interface. */
781                 valid_type = true;
782                 break;
783
784         case DCERPC_PKT_BIND_ACK:
785                 /* Server ack of bind. */
786                 valid_type = true;
787                 break;
788
789         case DCERPC_PKT_BIND_NAK:
790                 /* Server nack of bind. */
791                 valid_type = true;
792                 break;
793
794         case DCERPC_PKT_ALTER:
795                 /* Alter auth. */
796                 valid_type = true;
797                 break;
798
799         case DCERPC_PKT_ALTER_RESP:
800                 /* Reply to alter auth. */
801                 valid_type = true;
802                 break;
803
804         case DCERPC_PKT_AUTH3:
805                 /* not the real name!  this is undocumented! */
806                 valid_type = true;
807                 break;
808
809         case DCERPC_PKT_SHUTDOWN:
810                 /* Server to client request to shutdown. */
811                 valid_type = true;
812                 break;
813
814         case DCERPC_PKT_CO_CANCEL:
815                 /* Connection-oriented cancel request. */
816                 valid_type = true;
817                 break;
818
819         case DCERPC_PKT_ORPHANED:
820                 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
821                 valid_type = true;
822                 break;
823
824         case DCERPC_PKT_RTS:
825                 /* RTS packets used in ncacn_http */
826                 break;
827         }
828
829         if (!valid_type) {
830                 TALLOC_FREE(subreq);
831                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
832                 return;
833         }
834
835         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
836                 if (!allow_fragments) {
837                         TALLOC_FREE(subreq);
838                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
839                         return;
840                 }
841         }
842
843         if (conn->calls.active != NULL) {
844
845                 if (pkt->call_id != conn->calls.active->call_id) {
846                         TALLOC_FREE(subreq);
847                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
848                         return;
849                 }
850
851                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
852                         TALLOC_FREE(subreq);
853                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
854                         return;
855                 }
856
857                 call = conn->calls.active;
858
859                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
860                         conn->calls.active = NULL;
861                 }
862         } else {
863                 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
864                         TALLOC_FREE(subreq);
865                         // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
866                         return;
867                 }
868
869                 call = conn->calls.list;
870         }
871
872         for (call = conn->calls.list; call; call = call->next) {
873                 if (call->call_id == pkt->call_id) {
874                         break;
875                 }
876         }
877
878         if (call == NULL) {
879                 call = conn->calls.new_call;
880         }
881
882         if (call == NULL) {
883                 TALLOC_FREE(subreq);
884                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
885                 return;
886         }
887
888         if (call->incoming.handler == NULL) {
889                 TALLOC_FREE(subreq);
890                 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
891                 return;
892         }
893
894         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
895                 conn->calls.active = call;
896
897                 // TODO
898                 //
899                 // reassemble and return
900         }
901
902         error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
903         TALLOC_FREE(subreq);
904         if (!NT_STATUS_IS_OK(error)) {
905                 // disconnect and notify pending calls
906                 return;
907         }
908
909         if (conn->calls.new_call == NULL) {
910                 conn->loop.ev = NULL;
911                 return;
912         }
913
914         error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
915         if (!NT_STATUS_IS_OK(error)) {
916                 // disconnect and notify pending calls
917                 return;
918         }
919 }
920
921 struct dcerpc_do_bind_out_frag;
922
923 struct dcerpc_do_bind_state {
924         struct tevent_context *ev;
925         struct dcerpc_connection *conn;
926         struct dcerpc_call *call;
927         struct dcerpc_security *sec;
928         bool proposed_hdr_signing;
929         DATA_BLOB sec_in;
930         NTSTATUS sec_status;
931         DATA_BLOB sec_out;
932         struct dcerpc_do_bind_out_frag *out_frag;
933         uint32_t num_pres;
934         struct dcerpc_presentation **pres;
935         uint32_t remaining_pres;
936
937         uint32_t num_ctx;
938         struct dcerpc_ctx_list *ctx_list;
939         struct ndr_syntax_id features;
940 };
941
942 struct dcerpc_do_bind_out_frag {
943         struct tevent_context *ev;
944         struct dcerpc_connection *conn;
945         struct tevent_req *req;
946         enum dcerpc_pkt_type ptype;
947         DATA_BLOB blob;
948         struct iovec vector;
949         struct tevent_req *subreq_wait1;
950         struct tevent_req *subreq_wait2;
951 };
952
953 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
954                                    enum tevent_req_state req_state);
955
956 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
957 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
958
959 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
960                                               struct ncacn_packet *pkt,
961                                               DATA_BLOB frag);
962
963 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
964                                 struct tevent_context *ev,
965                                 struct dcerpc_connection *conn,
966                                 struct dcerpc_call *call,
967                                 struct dcerpc_security *sec,
968                                 uint32_t num_pres,
969                                 struct dcerpc_presentation **pres)
970 {
971         struct tevent_req *req;
972         struct dcerpc_do_bind_state *state;
973         struct tevent_req *subreq;
974
975         req = tevent_req_create(mem_ctx, &state,
976                                 struct dcerpc_do_bind_state);
977         if (req == NULL) {
978                 return NULL;
979         }
980         state->ev = ev;
981         state->conn = conn;
982         state->call = call;
983         state->sec = sec;
984         state->num_pres = num_pres;
985         state->pres = pres;
986
987         state->call->incoming.private_data = req;
988         state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
989         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
990
991         tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
992         tevent_req_defer_callback(req, ev);
993
994         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
995                 subreq = gensec_update_send(state, ev,
996                                             state->sec->gensec,
997                                             state->sec_in);
998                 if (tevent_req_nomem(subreq, req)) {
999                         return tevent_req_post(req, ev);
1000                 }
1001                 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1002
1003                 return req;
1004         }
1005
1006         state->sec_status = NT_STATUS_OK;
1007
1008         subreq = tevent_queue_wait_send(state, state->ev,
1009                                         state->conn->calls.out_queue);
1010         if (tevent_req_nomem(subreq, req)) {
1011                 return tevent_req_post(req, ev);
1012         }
1013         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1014
1015         return req;
1016 }
1017
1018 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1019                                    enum tevent_req_state req_state)
1020 {
1021         struct dcerpc_do_bind_state *state =
1022                 tevent_req_data(req,
1023                 struct dcerpc_do_bind_state);
1024
1025         if (state->out_frag != NULL) {
1026                 state->out_frag->req = NULL;
1027                 state->out_frag = NULL;
1028         }
1029
1030         if (state->call != NULL) {
1031                 ZERO_STRUCT(state->call->incoming);
1032                 DLIST_REMOVE(state->conn->calls.list, state->call);
1033                 state->call = NULL;
1034         }
1035 }
1036
1037 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1038 {
1039         struct tevent_req *req =
1040                 tevent_req_callback_data(subreq,
1041                 struct tevent_req);
1042         struct dcerpc_do_bind_state *state =
1043                 tevent_req_data(req,
1044                 struct dcerpc_do_bind_state);
1045         NTSTATUS status;
1046
1047         data_blob_free(&state->sec_out);
1048         status = gensec_update_recv(subreq, state, &state->sec_out);
1049         TALLOC_FREE(subreq);
1050         data_blob_free(&state->sec_in);
1051         state->sec_status = status;
1052         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1053                 status = NT_STATUS_OK;
1054         }
1055         if (!NT_STATUS_IS_OK(status)) {
1056                 tevent_req_nterror(req, status);
1057                 return;
1058         }
1059
1060         if (NT_STATUS_IS_OK(state->sec_status) &&
1061             state->sec_out.length == 0)
1062         {
1063                 tevent_req_done(req);
1064                 return;
1065         }
1066
1067         if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1068                 state->sec->client_hdr_signing =
1069                         gensec_have_feature(state->sec->gensec,
1070                                             GENSEC_FEATURE_SIGN_PKT_HEADER);
1071         }
1072
1073         subreq = tevent_queue_wait_send(state, state->ev,
1074                                         state->conn->calls.out_queue);
1075         if (tevent_req_nomem(subreq, req)) {
1076                 return;
1077         }
1078         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1079 }
1080
1081 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1082 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1083 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1084
1085 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1086 {
1087         struct tevent_req *req =
1088                 tevent_req_callback_data(subreq,
1089                 struct tevent_req);
1090         struct dcerpc_do_bind_state *state =
1091                 tevent_req_data(req,
1092                 struct dcerpc_do_bind_state);
1093         struct dcerpc_do_bind_out_frag *frag;
1094         size_t auth_len = 0;
1095         NTSTATUS status;
1096         DATA_BLOB auth_info = data_blob_null;
1097         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1098         union dcerpc_payload u;
1099         uint32_t i;
1100         bool require_ack = false;
1101         bool use_trans = true;
1102         bool ok;
1103
1104         ok = tevent_queue_wait_recv(subreq);
1105         if (!ok) {
1106                 //status = NT_STATUS_INTERNAL_ERROR;
1107                 tevent_req_oom(req);
1108                 return;
1109         }
1110         TALLOC_FREE(subreq);
1111
1112         /*
1113          * the fragment belongs to the connection instead of the request
1114          * because it has to remain in case the request is canceled
1115          */
1116         frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1117         if (tevent_req_nomem(frag, req)) {
1118                 return;
1119         }
1120         frag->ev = state->ev;
1121         frag->conn = state->conn;
1122         frag->req = req;
1123         state->out_frag = frag;
1124
1125         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1126                 if (state->sec->client_hdr_signing &&
1127                     !state->proposed_hdr_signing)
1128                 {
1129                         state->proposed_hdr_signing = true;
1130                         pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1131                         require_ack = true;
1132                 }
1133         }
1134
1135         //TODO : DCERPC_PFC_FLAG_CONC_MPX
1136
1137         //TODO: remaining_pres
1138
1139         if (!state->conn->features.bind_done) {
1140                 frag->ptype = DCERPC_PKT_BIND;
1141         } else if (require_ack) {
1142                 frag->ptype = DCERPC_PKT_ALTER;
1143         } else if (state->remaining_pres > 0) {
1144                 frag->ptype = DCERPC_PKT_ALTER;
1145         } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1146                 frag->ptype = DCERPC_PKT_ALTER;
1147         } else {
1148                 frag->ptype = DCERPC_PKT_AUTH3;
1149         }
1150
1151         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1152                 status = dcerpc_auth_blob(frag,
1153                                           state->sec->auth_type,
1154                                           state->sec->auth_level,
1155                                           0, /* auth_pad_length */
1156                                           state->sec->context_id, /* auth_context_id */
1157                                           &state->sec_out,
1158                                           &auth_info);
1159                 if (!NT_STATUS_IS_OK(status)) {
1160                         tevent_req_nterror(req, status);
1161                         return;
1162                 }
1163
1164                 auth_len = auth_info.length;
1165
1166                 if (auth_len) {
1167                         auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1168                 }
1169         }
1170
1171         state->num_ctx = state->num_pres;
1172         if (!state->conn->assoc->negotiate_done) {
1173                 state->num_ctx += 1;
1174         }
1175
1176         state->ctx_list = talloc_zero_array(frag,
1177                                             struct dcerpc_ctx_list,
1178                                             state->num_ctx);
1179         if (tevent_req_nomem(state->ctx_list, req)) {
1180                 return;
1181         }
1182
1183         for (i=0; i < state->num_pres; i++) {
1184                 state->ctx_list[i] = state->pres[i]->negotiate.req;
1185         }
1186
1187         if (!state->conn->assoc->negotiate_done) {
1188                 state->features = dcerpc_construct_bind_time_features(
1189                                         state->conn->assoc->client_features);
1190
1191                 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1192                 if (i > 0) {
1193                         state->ctx_list[i].abstract_syntax =
1194                                 state->ctx_list[i-1].abstract_syntax;
1195                 }
1196                 state->ctx_list[i].num_transfer_syntaxes = 1;
1197                 state->ctx_list[i].transfer_syntaxes = &state->features;
1198         }
1199
1200         switch (frag->ptype) {
1201         case DCERPC_PKT_BIND:
1202         case DCERPC_PKT_ALTER:
1203                 u.bind.max_xmit_frag    = state->conn->features.max_xmit_frag;
1204                 u.bind.max_recv_frag    = state->conn->features.max_recv_frag;
1205                 u.bind.assoc_group_id   = state->conn->assoc->assoc_group_id;
1206                 u.bind.num_contexts     = state->num_ctx;
1207                 u.bind.ctx_list         = state->ctx_list;
1208                 u.bind.auth_info        = auth_info;
1209                 break;
1210
1211         case DCERPC_PKT_AUTH3:
1212                 u.auth3._pad            = 0;
1213                 u.auth3.auth_info       = auth_info;
1214                 break;
1215         default:
1216                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1217                 return;
1218         }
1219
1220         status = dcerpc_ncacn_packet_blob(frag,
1221                                           frag->ptype,
1222                                           pfc_flags,
1223                                           auth_len,
1224                                           state->call->call_id,
1225                                           &u,
1226                                           &frag->blob);
1227         if (!NT_STATUS_IS_OK(status)) {
1228                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1229                 tevent_req_nterror(req, status);
1230                 return;
1231         }
1232
1233         if (frag->ptype == DCERPC_PKT_AUTH3) {
1234                 use_trans = false;
1235         }
1236
1237         if (frag->conn->transport.use_trans_fn == NULL) {
1238                 use_trans = false;
1239         }
1240
1241         if (frag->conn->loop.subreq != NULL) {
1242                 use_trans = false;
1243         }
1244
1245         if (frag->conn->features.concurrent_multiplex) {
1246                 use_trans = false;
1247         }
1248
1249         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1250                 use_trans = false;
1251         }
1252
1253         if (use_trans) {
1254                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1255                                                 frag->ev,
1256                                                 frag->conn->transport.write_queue);
1257                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1258                         return;
1259                 }
1260                 tevent_req_set_callback(frag->subreq_wait1,
1261                                         dcerpc_do_bind_out_frag_trans_wait1,
1262                                         frag);
1263                 /*
1264                  * we need to block reads until our write is
1265                  * the next in the write queue.
1266                  */
1267                 frag->conn->loop.subreq = frag->subreq_wait1;
1268                 frag->conn->loop.ev = frag->ev;
1269         }
1270
1271         /*
1272          * We need to add a dcerpc_write_fragment_queue_send/recv()
1273          */
1274
1275         frag->vector.iov_base = frag->blob.data;
1276         frag->vector.iov_len = frag->blob.length;
1277         subreq = tstream_writev_queue_send(frag, frag->ev,
1278                                            frag->conn->transport.stream,
1279                                            frag->conn->transport.write_queue,
1280                                            &frag->vector, 1);
1281         if (tevent_req_nomem(subreq, req)) {
1282                 return;
1283         }
1284         tevent_req_set_callback(subreq,
1285                                 dcerpc_do_bind_out_frag_done,
1286                                 frag);
1287
1288         if (use_trans) {
1289                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1290                                                 frag->ev,
1291                                                 frag->conn->transport.write_queue);
1292                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1293                         return;
1294                 }
1295                 tevent_req_set_callback(frag->subreq_wait2,
1296                                         dcerpc_do_bind_out_frag_trans_wait2,
1297                                         frag);
1298         }
1299
1300         if (frag->ptype == DCERPC_PKT_AUTH3) {
1301                 return;
1302         }
1303
1304         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1305         if (tevent_req_nterror(req, status)) {
1306                 return;
1307         }
1308 }
1309
1310 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1311 {
1312         struct dcerpc_do_bind_out_frag *frag =
1313                 tevent_req_callback_data(subreq,
1314                 struct dcerpc_do_bind_out_frag);
1315         struct tevent_req *req = frag->req;
1316         NTSTATUS status;
1317         bool ok;
1318
1319         /*
1320          * TODO; what if the caller has been free'ed?
1321          */
1322
1323         frag->subreq_wait1 = NULL;
1324         frag->conn->loop.subreq = NULL;
1325
1326         ok = tevent_queue_wait_recv(subreq);
1327         if (!ok) {
1328                 status = NT_STATUS_INTERNAL_ERROR;
1329                 TALLOC_FREE(frag);
1330                 if (req) {
1331                         tevent_req_nterror(req, status);
1332                 }
1333                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1334                 return;
1335         }
1336
1337         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1338                 /*
1339                  * We added 3 entries into the queue,
1340                  * wait1, writev and wait2.
1341                  *
1342                  * There's more to write, we should not block
1343                  * further writev calls for a trans call.
1344                  *
1345                  * The wait2 stage will trigger the read.
1346                  */
1347                 TALLOC_FREE(subreq);
1348                 return;
1349         }
1350
1351         /*
1352          * we don't need wait2 anymore, we're sure that
1353          * we'll do a trans call.
1354          */
1355         TALLOC_FREE(frag->subreq_wait2);
1356
1357         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1358         if (!NT_STATUS_IS_OK(status)) {
1359                 TALLOC_FREE(frag);
1360                 if (req) {
1361                         tevent_req_nterror(req, status);
1362                 }
1363                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1364                 return;
1365         }
1366
1367         /* we free subreq after tstream_cli_np_use_trans */
1368         TALLOC_FREE(subreq);
1369
1370         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 TALLOC_FREE(frag);
1373                 if (req) {
1374                         tevent_req_nterror(req, status);
1375                 }
1376                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1377                 return;
1378         }
1379 }
1380
1381 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1382 {
1383         struct dcerpc_do_bind_out_frag *frag =
1384                 tevent_req_callback_data(subreq,
1385                 struct dcerpc_do_bind_out_frag);
1386         struct tevent_req *req = frag->req;
1387         NTSTATUS status;
1388         int ret;
1389         int sys_errno;
1390
1391         /*
1392          * If the caller has been free'ed, we have should
1393          * ignore any errors and just free 'frag'
1394          */
1395         if (req) {
1396                 struct dcerpc_do_bind_state *state =
1397                         tevent_req_data(req,
1398                         struct dcerpc_do_bind_state);
1399
1400                 state->out_frag = NULL;
1401         }
1402
1403         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1404         TALLOC_FREE(subreq);
1405         if (ret == -1) {
1406                 TALLOC_FREE(frag);
1407                 status = map_nt_error_from_unix_common(sys_errno);
1408                 if (req) {
1409                         tevent_req_nterror(req, status);
1410                 }
1411                 return;
1412         }
1413
1414         if (frag->ptype == DCERPC_PKT_AUTH3) {
1415                 TALLOC_FREE(frag);
1416                 if (req == NULL) {
1417                         return;
1418                 }
1419                 tevent_req_done(req);
1420                 return;
1421         }
1422
1423         if (frag->subreq_wait2 != NULL) {
1424                 return;
1425         }
1426
1427         TALLOC_FREE(frag);
1428
1429         /* we need to wait for incoming pdus */
1430 }
1431
1432 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1433 {
1434         struct dcerpc_do_bind_out_frag *frag =
1435                 tevent_req_callback_data(subreq,
1436                 struct dcerpc_do_bind_out_frag);
1437         struct tevent_req *req = frag->req;
1438         NTSTATUS status;
1439         bool ok;
1440
1441         frag->subreq_wait2 = NULL;
1442
1443         ok = tevent_queue_wait_recv(subreq);
1444         if (!ok) {
1445                 status = NT_STATUS_INTERNAL_ERROR;
1446                 TALLOC_FREE(frag);
1447                 if (req) {
1448                         tevent_req_nterror(req, status);
1449                 }
1450                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1451                 return;
1452         }
1453
1454         TALLOC_FREE(subreq);
1455
1456         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1457         if (!NT_STATUS_IS_OK(status)) {
1458                 TALLOC_FREE(frag);
1459                 if (req) {
1460                         tevent_req_nterror(req, status);
1461                 }
1462                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1463                 return;
1464         }
1465
1466         TALLOC_FREE(frag);
1467
1468         /* we need to wait for incoming pdus */
1469 }
1470
1471 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
1472                                                  struct ncacn_packet *pkt,
1473                                                  DATA_BLOB frag)
1474 {
1475         struct tevent_req *req =
1476                 talloc_get_type_abort(private_data,
1477                 struct tevent_req);
1478         struct dcerpc_do_bind_state *state =
1479                 tevent_req_data(req,
1480                 struct dcerpc_do_bind_state);
1481         NTSTATUS status;
1482         size_t i;
1483
1484         /* Ensure we have the correct type. */
1485         switch (pkt->ptype) {
1486         case DCERPC_PKT_BIND_ACK:
1487         case DCERPC_PKT_ALTER_RESP:
1488                 if (!state->conn->features.bind_done) {
1489                         if (pkt->u.bind_ack.max_recv_frag < 1234) {
1490                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1491                         }
1492                         if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1493                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1494                         }
1495                         state->conn->features.max_recv_frag =
1496                                 pkt->u.bind_ack.max_recv_frag;
1497                         state->conn->features.max_xmit_frag =
1498                                 pkt->u.bind_ack.max_xmit_frag;
1499
1500                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1501                                 state->conn->features.concurrent_multiplex = true;
1502                         }
1503
1504                         state->conn->features.bind_done = true;
1505                 }
1506
1507                 if (!state->conn->assoc->negotiate_done) {
1508                         state->conn->assoc->negotiate_done = true;
1509                         state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1510                 }
1511
1512                 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1513                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1514                 }
1515
1516                 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1517                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1518                 }
1519
1520                 if (state->proposed_hdr_signing) {
1521                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1522                                 state->sec->hdr_signing = true;
1523                         }
1524                 }
1525
1526                 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1527                         struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1528
1529                         if (i < state->num_pres) {
1530                                 state->pres[i]->negotiate.ack = *ack;
1531                                 continue;
1532                         }
1533
1534                         if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1535                                 continue;
1536                         }
1537
1538                         state->conn->assoc->features = state->conn->assoc->client_features;
1539                         state->conn->assoc->features &= ack->reason.negotiate;
1540                 }
1541
1542                 for (i = 0; i < state->num_pres; i++) {
1543                         struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1544                         bool ok;
1545
1546                         if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1547                                 continue;
1548                         }
1549
1550                         ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1551                                                  &ack->syntax);
1552                         if (!ok) {
1553                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1554                         }
1555                 }
1556
1557                 if (pkt->auth_length >= 8) {
1558                         struct tevent_req *subreq;
1559
1560                         state->sec_in = data_blob_talloc(state,
1561                                         pkt->u.bind_ack.auth_info.data + 8,
1562                                         pkt->u.bind_ack.auth_info.length - 8);
1563
1564                         subreq = gensec_update_send(state, state->ev,
1565                                                     state->sec->gensec,
1566                                                     state->sec_in);
1567                         if (tevent_req_nomem(subreq, req)) {
1568                                 return NT_STATUS_OK;
1569                         }
1570                         tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1571                         return NT_STATUS_OK;
1572                 }
1573
1574                 tevent_req_done(req);
1575                 return NT_STATUS_OK;
1576
1577         //case DCERPC_PKT_ALTER_RESP:
1578                 if (pkt->auth_length != 0) {
1579                         return NT_STATUS_NOT_IMPLEMENTED;
1580                 }
1581
1582                 return NT_STATUS_NOT_IMPLEMENTED;
1583 //TODO
1584 #if 0
1585                 /* Point the return values at the NDR data. */
1586                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1587
1588                 if (pkt->auth_length) {
1589                         /* We've already done integer wrap tests in
1590                          * dcerpc_check_auth(). */
1591                         payload.length = frag.length
1592                                          - DCERPC_RESPONSE_LENGTH
1593                                          - pad_len
1594                                          - DCERPC_AUTH_TRAILER_LENGTH
1595                                          - pkt->auth_length;
1596                 } else {
1597                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1598                 }
1599
1600                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1601                         if (pkt->drep[0] & DCERPC_DREP_LE) {
1602                                 state->response.bigendian = false;
1603                         } else {
1604                                 state->response.bigendian = true;
1605                         }
1606                 }
1607
1608                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1609                            (long unsigned int)frag.length,
1610                            (long unsigned int)payload.length,
1611                            (unsigned int)pad_len));
1612
1613                 /*
1614                  * If this is the first reply, and the allocation hint is
1615                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
1616                  * correct size.
1617                  */
1618
1619                 if ((state->response.blob.length == 0) &&
1620                     pkt->u.response.alloc_hint &&
1621                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
1622                         ok = data_blob_realloc(state, &state->response.blob,
1623                                                pkt->u.response.alloc_hint);
1624                         if (!ok) {
1625                                 DEBUG(0, ("reply alloc hint %d too "
1626                                           "large to allocate\n",
1627                                     (int)pkt->u.response.alloc_hint));
1628                                 return NT_STATUS_NO_MEMORY;
1629                         }
1630                 }
1631
1632                 new_total = state->response.ofs + payload.length;
1633
1634                 if (new_total > 15 * 1024 *1024) {
1635                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1636                 }
1637
1638                 missing = new_total - state->response.blob.length;
1639
1640                 if (missing > 0) {
1641                         ok = data_blob_realloc(state, &state->response.blob,
1642                                                new_total);
1643                         if (!ok) {
1644                                 DEBUG(0, ("reply alloc hint %d too "
1645                                           "large to allocate\n",
1646                                     (int)pkt->u.response.alloc_hint));
1647                                 return NT_STATUS_NO_MEMORY;
1648                         }
1649                 }
1650
1651                 memcpy(state->response.blob.data + state->response.ofs,
1652                        payload.data, payload.length);
1653                 state->response.ofs += payload.length;
1654
1655                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1656                         tevent_req_done(req);//TODO
1657                         return NT_STATUS_OK;
1658                 }
1659                 return NT_STATUS_OK;
1660 #endif
1661                 return NT_STATUS_NOT_IMPLEMENTED;
1662
1663         case DCERPC_PKT_FAULT:
1664
1665                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1666                           "code %s received from %s!\n",
1667                           dcerpc_errstr(talloc_tos(),
1668                           pkt->u.fault.status),
1669                           "TODO"));
1670
1671                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1672                 if (NT_STATUS_IS_OK(status)) {
1673                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
1674                 }
1675
1676                 tevent_req_nterror(req, status);//TODO
1677                 return NT_STATUS_OK;
1678         default:
1679                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1680                           (unsigned int)pkt->ptype,
1681                          "TODO"));
1682                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1683         }
1684
1685         return NT_STATUS_RPC_PROTOCOL_ERROR;
1686 }
1687
1688 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1689 {
1690         struct dcerpc_do_bind_state *state =
1691                 tevent_req_data(req,
1692                 struct dcerpc_do_bind_state);
1693         NTSTATUS status;
1694
1695         if (tevent_req_is_nterror(req, &status)) {
1696                 tevent_req_received(req);
1697                 return status;
1698         }
1699
1700         if (!NT_STATUS_IS_OK(state->sec_status)) {
1701                 status = state->sec_status;
1702                 tevent_req_received(req);
1703                 return status;
1704         }
1705
1706         tevent_req_received(req);
1707         return NT_STATUS_OK;
1708 }
1709
1710 struct dcerpc_do_request_out_frag;
1711
1712 struct dcerpc_do_request_state {
1713         struct tevent_context *ev;
1714         struct dcerpc_connection *conn;
1715         struct dcerpc_call *call;
1716         const struct GUID *object;
1717         uint16_t opnum;
1718         struct {
1719                 const DATA_BLOB *blob;
1720                 size_t ofs;
1721                 bool bigendian;
1722                 DATA_BLOB trailer;
1723                 size_t trailer_ofs;
1724         } request;
1725         bool verify_bitmask1;
1726         bool verify_pcontext;
1727         bool got_first;
1728         struct dcerpc_do_request_out_frag *out_frag;
1729         struct {
1730                 DATA_BLOB blob;
1731                 size_t ofs;
1732                 bool bigendian;
1733         } response;
1734 };
1735
1736 struct dcerpc_do_request_out_frag {
1737         struct tevent_context *ev;
1738         struct dcerpc_connection *conn;
1739         struct tevent_req *req;
1740         DATA_BLOB blob;
1741         bool is_last;
1742         struct iovec vector;
1743         struct tevent_req *subreq_wait1;
1744         struct tevent_req *subreq_wait2;
1745 };
1746
1747 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1748                                       enum tevent_req_state req_state);
1749
1750 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1751 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1752                                             void *private_data);
1753
1754 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
1755                                                  struct ncacn_packet *pkt,
1756                                                  DATA_BLOB frag);
1757
1758 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1759                                 struct tevent_context *ev,
1760                                 struct dcerpc_connection *conn,
1761                                 struct dcerpc_call *call,
1762                                 const struct GUID *object,
1763                                 uint16_t opnum,
1764                                 const DATA_BLOB *request,
1765                                 bool bigendian)
1766 {
1767         struct tevent_req *req;
1768         struct dcerpc_do_request_state *state;
1769         bool ok;
1770
1771         req = tevent_req_create(mem_ctx, &state,
1772                                 struct dcerpc_do_request_state);
1773         if (req == NULL) {
1774                 return NULL;
1775         }
1776         state->ev = ev;
1777         state->conn = conn;
1778         state->call = call;
1779         state->object = object;
1780         state->opnum = opnum;
1781         state->request.blob = request;
1782         state->request.bigendian = bigendian;
1783
1784         dcerpc_do_request_verification_trailer(req);
1785         if (!tevent_req_is_in_progress(req)) {
1786                 return tevent_req_post(req, ev);
1787         }
1788
1789         state->call->incoming.private_data = req;
1790         state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1791         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1792
1793         tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1794         tevent_req_defer_callback(req, ev);
1795
1796         ok = tevent_queue_add(state->conn->calls.out_queue,
1797                               state->ev,
1798                               req,
1799                               dcerpc_do_request_out_frag_next,
1800                               NULL);
1801         if (!ok) {
1802                 tevent_req_nomem(NULL, req);
1803                 return tevent_req_post(req, ev);
1804         }
1805
1806         return req;
1807 }
1808
1809 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1810                                       enum tevent_req_state req_state)
1811 {
1812         struct dcerpc_do_request_state *state =
1813                 tevent_req_data(req,
1814                 struct dcerpc_do_request_state);
1815
1816         if (state->out_frag != NULL) {
1817                 state->out_frag->req = NULL;
1818                 state->out_frag = NULL;
1819         }
1820
1821         if (state->call != NULL) {
1822                 if (state->call == state->conn->calls.active) {
1823                         state->conn->calls.active = NULL;
1824                 }
1825                 ZERO_STRUCT(state->call->incoming);
1826                 DLIST_REMOVE(state->conn->calls.list, state->call);
1827                 state->call = NULL;
1828         }
1829 }
1830
1831 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1832 {
1833         struct dcerpc_do_request_state *state =
1834                 tevent_req_data(req,
1835                 struct dcerpc_do_request_state);
1836         struct dcerpc_sec_verification_trailer *t;
1837         struct dcerpc_sec_vt *c = NULL;
1838         struct ndr_push *ndr = NULL;
1839         enum ndr_err_code ndr_err;
1840         size_t align = 0;
1841         size_t pad = 0;
1842
1843         if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1844                 return;
1845         }
1846
1847         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1848         if (tevent_req_nomem(t, req)) {
1849                 return;
1850         }
1851
1852         if (!state->call->sec->verified_bitmask1) {
1853                 t->commands = talloc_realloc(t, t->commands,
1854                                              struct dcerpc_sec_vt,
1855                                              t->count.count + 1);
1856                 if (tevent_req_nomem(t->commands, req)) {
1857                         return;
1858                 }
1859                 c = &t->commands[t->count.count++];
1860                 ZERO_STRUCTP(c);
1861
1862                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1863                 if (state->call->sec->client_hdr_signing) {
1864                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1865                 }
1866                 state->verify_bitmask1 = true;
1867         }
1868
1869         if (!state->call->pres->verified_pcontext) {
1870                 t->commands = talloc_realloc(t, t->commands,
1871                                              struct dcerpc_sec_vt,
1872                                              t->count.count + 1);
1873                 if (tevent_req_nomem(t->commands, req)) {
1874                         return;
1875                 }
1876                 c = &t->commands[t->count.count++];
1877                 ZERO_STRUCTP(c);
1878
1879                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1880                 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1881                 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1882
1883                 state->verify_pcontext = true;
1884         }
1885
1886         if (!state->call->sec->hdr_signing) {
1887                 t->commands = talloc_realloc(t, t->commands,
1888                                              struct dcerpc_sec_vt,
1889                                              t->count.count + 1);
1890                 if (tevent_req_nomem(t->commands, req)) {
1891                         return;
1892                 }
1893                 c = &t->commands[t->count.count++];
1894                 ZERO_STRUCTP(c);
1895
1896                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1897                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1898                 if (state->request.bigendian) {
1899                         c->u.header2.drep[0] = 0;
1900                 } else {
1901                         c->u.header2.drep[0] = DCERPC_DREP_LE;
1902                 }
1903                 c->u.header2.drep[1] = 0;
1904                 c->u.header2.drep[2] = 0;
1905                 c->u.header2.drep[3] = 0;
1906                 c->u.header2.call_id = state->call->call_id;
1907                 c->u.header2.context_id = 0;
1908                 c->u.header2.opnum = state->opnum;
1909         }
1910
1911         if (t->count.count == 0) {
1912                 TALLOC_FREE(t);
1913                 return;
1914         }
1915
1916         c = &t->commands[t->count.count - 1];
1917         c->command |= DCERPC_SEC_VT_COMMAND_END;
1918
1919         if (DEBUGLEVEL >= 10) {
1920                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1921         }
1922
1923         ndr = ndr_push_init_ctx(state);
1924         if (tevent_req_nomem(ndr, req)) {
1925                 return;
1926         }
1927
1928         //TODO if (state->request.bigendian)
1929
1930         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1931                                                 NDR_SCALARS | NDR_BUFFERS,
1932                                                 t);
1933         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1934                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1935                 tevent_req_nterror(req, status);
1936                 return;
1937         }
1938         state->request.trailer = ndr_push_blob(ndr);
1939
1940         align = state->request.blob->length & 0x3;
1941         if (align > 0) {
1942                 pad = 4 - align;
1943         }
1944         if (pad > 0) {
1945                 bool ok;
1946                 uint8_t *p;
1947                 const uint8_t zeros[4] = { 0, };
1948
1949                 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
1950                 if (!ok) {
1951                         tevent_req_oom(req);
1952                         return;
1953                 }
1954
1955                 /* move the padding to the start */
1956                 p = state->request.trailer.data;
1957                 memmove(p + pad, p, state->request.trailer.length - pad);
1958                 memset(p, 0, pad);
1959         }
1960
1961         return;
1962 }
1963
1964 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
1965 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
1966 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
1967
1968 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1969                                             void *private_data)
1970 {
1971         struct dcerpc_do_request_state *state =
1972                 tevent_req_data(req,
1973                 struct dcerpc_do_request_state);
1974         struct dcerpc_do_request_out_frag *frag;
1975         size_t hdr_len = DCERPC_REQUEST_LENGTH;
1976         size_t auth_len;
1977         size_t frag_len;
1978         uint8_t flags = 0;
1979         size_t pad_len;
1980         size_t data_left;
1981         size_t data_thistime;
1982         size_t trailer_left;
1983         size_t trailer_thistime = 0;
1984         size_t total_left;
1985         size_t total_thistime;
1986         NTSTATUS status;
1987         union dcerpc_payload u;
1988         bool ok;
1989         struct tevent_req *subreq;
1990         bool use_trans = true;
1991
1992         if (state->object) {
1993                 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1994                 hdr_len += 16;
1995         }
1996
1997         /*
1998          * the fragment belongs to the connection instead of the request
1999          * because it has to remain in case the request is canceled
2000          */
2001         frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2002         if (tevent_req_nomem(frag, req)) {
2003                 return;
2004         }
2005         frag->ev = state->ev;
2006         frag->conn = state->conn;
2007         frag->req = req;
2008         state->out_frag = frag;
2009
2010         data_left = state->request.blob->length - state->request.ofs;
2011         trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2012         total_left = data_left + trailer_left;
2013         if (total_left < data_left || total_left < trailer_left) {
2014                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2015                 return;
2016         }
2017
2018         status = dcerpc_guess_pdu_sizes(state->call->sec,
2019                                     hdr_len, total_left,
2020                                     state->conn->features.max_xmit_frag,
2021                                     16,//TODO
2022                                     &total_thistime,
2023                                     &frag_len, &auth_len, &pad_len);
2024         if (!NT_STATUS_IS_OK(status)) {
2025                 tevent_req_nterror(req, status);
2026                 return;
2027         }
2028
2029         if (state->request.ofs == 0) {
2030                 flags |= DCERPC_PFC_FLAG_FIRST;
2031         }
2032
2033         if (total_thistime == total_left) {
2034                 flags |= DCERPC_PFC_FLAG_LAST;
2035         }
2036
2037         data_thistime = MIN(total_thistime, data_left);
2038         if (data_thistime < total_thistime) {
2039                 trailer_thistime = total_thistime - data_thistime;
2040         }
2041
2042         ZERO_STRUCT(u.request);
2043
2044         u.request.alloc_hint    = total_left;
2045         u.request.context_id    = state->call->pres->context_id;
2046         u.request.opnum         = state->opnum;
2047         if (state->object) {
2048                 u.request.object.object = *state->object;
2049         }
2050 //TODO pass state->request.bigendian
2051         status = dcerpc_ncacn_packet_blob(frag,
2052                                           DCERPC_PKT_REQUEST,
2053                                           flags,
2054                                           auth_len,
2055                                           state->call->call_id,
2056                                           &u,
2057                                           &frag->blob);
2058         if (!NT_STATUS_IS_OK(status)) {
2059                 tevent_req_nterror(req, status);
2060                 return;
2061         }
2062
2063         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2064          * compute it right for requests because the auth trailer is missing
2065          * at this stage */
2066         dcerpc_set_frag_length(&frag->blob, frag_len);
2067
2068         if (data_thistime > 0) {
2069                 const uint8_t *data_ptr;
2070
2071                 data_ptr = state->request.blob->data;
2072                 data_ptr += state->request.ofs;
2073
2074                 /* Copy in the data. */
2075                 ok = data_blob_append(frag, &frag->blob,
2076                                       data_ptr, data_thistime);
2077                 if (!ok) {
2078                         tevent_req_oom(req);
2079                         return;
2080                 }
2081
2082                 state->request.ofs += data_thistime;
2083         }
2084
2085         if (trailer_thistime > 0) {
2086                 const uint8_t *trailer_ptr;
2087
2088                 trailer_ptr = state->request.trailer.data;
2089                 trailer_ptr += state->request.trailer_ofs;
2090
2091                 /* Copy in the data. */
2092                 ok = data_blob_append(frag, &frag->blob,
2093                                       trailer_ptr, trailer_thistime);
2094                 if (!ok) {
2095                         tevent_req_oom(req);
2096                         return;
2097                 }
2098
2099                 state->request.trailer_ofs += trailer_thistime;
2100         }
2101
2102         switch (state->call->sec->auth_level) {
2103         case DCERPC_AUTH_LEVEL_NONE:
2104         case DCERPC_AUTH_LEVEL_CONNECT:
2105         case DCERPC_AUTH_LEVEL_PACKET:
2106                 break;
2107         case DCERPC_AUTH_LEVEL_INTEGRITY:
2108         case DCERPC_AUTH_LEVEL_PRIVACY:
2109                 status = dcerpc_response_auth_blob(state->call->sec,
2110                                                 pad_len,
2111                                                 &frag->blob);
2112                 if (!NT_STATUS_IS_OK(status)) {
2113                         tevent_req_nterror(req, status);
2114                         return;
2115                 }
2116                 break;
2117         default:
2118                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2119                 return;
2120         }
2121
2122         frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2123
2124         if (!frag->is_last) {
2125                 use_trans = false;
2126         }
2127
2128         if (frag->conn->transport.use_trans_fn == NULL) {
2129                 use_trans = false;
2130         }
2131
2132         if (frag->conn->loop.subreq != NULL) {
2133                 use_trans = false;
2134         }
2135
2136         if (frag->conn->features.concurrent_multiplex) {
2137                 use_trans = false;
2138         }
2139
2140         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2141                 use_trans = false;
2142         }
2143
2144         if (use_trans) {
2145                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2146                                                 frag->ev,
2147                                                 frag->conn->transport.write_queue);
2148                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2149                         return;
2150                 }
2151                 tevent_req_set_callback(frag->subreq_wait1,
2152                                         dcerpc_do_request_out_frag_trans_wait1,
2153                                         frag);
2154                 /*
2155                  * we need to block reads until our write is
2156                  * the next in the write queue.
2157                  */
2158                 frag->conn->loop.subreq = frag->subreq_wait1;
2159                 frag->conn->loop.ev = frag->ev;
2160         }
2161
2162         /*
2163          * We need to add a dcerpc_write_fragment_queue_send/recv()
2164          */
2165
2166         frag->vector.iov_base = frag->blob.data;
2167         frag->vector.iov_len = frag->blob.length;
2168         subreq = tstream_writev_queue_send(frag, frag->ev,
2169                                            frag->conn->transport.stream,
2170                                            frag->conn->transport.write_queue,
2171                                            &frag->vector, 1);
2172         if (tevent_req_nomem(subreq, req)) {
2173                 return;
2174         }
2175         tevent_req_set_callback(subreq,
2176                                 dcerpc_do_request_out_frag_done,
2177                                 frag);
2178
2179         if (use_trans) {
2180                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2181                                                 frag->ev,
2182                                                 frag->conn->transport.write_queue);
2183                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2184                         return;
2185                 }
2186                 tevent_req_set_callback(frag->subreq_wait2,
2187                                         dcerpc_do_request_out_frag_trans_wait2,
2188                                         frag);
2189         }
2190
2191         if (!frag->is_last) {
2192                 return;
2193         }
2194
2195         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2196         if (tevent_req_nterror(req, status)) {
2197                 return;
2198         }
2199 }
2200
2201 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2202 {
2203         struct dcerpc_do_request_out_frag *frag =
2204                 tevent_req_callback_data(subreq,
2205                 struct dcerpc_do_request_out_frag);
2206         struct tevent_req *req = frag->req;
2207         NTSTATUS status;
2208         bool ok;
2209
2210         /*
2211          * TODO; what if the caller has been free'ed?
2212          */
2213
2214         frag->subreq_wait1 = NULL;
2215         frag->conn->loop.subreq = NULL;
2216
2217         ok = tevent_queue_wait_recv(subreq);
2218         if (!ok) {
2219                 status = NT_STATUS_INTERNAL_ERROR;
2220                 TALLOC_FREE(frag);
2221                 if (req) {
2222                         tevent_req_nterror(req, status);
2223                 }
2224                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2225                 return;
2226         }
2227
2228         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2229                 /*
2230                  * We added 3 entries into the queue,
2231                  * wait1, writev and wait2.
2232                  *
2233                  * There's more to write, we should not block
2234                  * further writev calls for a trans call.
2235                  *
2236                  * The wait2 stage will trigger the read.
2237                  */
2238                 TALLOC_FREE(subreq);
2239                 return;
2240         }
2241
2242         /*
2243          * we don't need wait2 anymore, we're sure that
2244          * we'll do a trans call.
2245          */
2246         TALLOC_FREE(frag->subreq_wait2);
2247
2248         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2249         if (!NT_STATUS_IS_OK(status)) {
2250                 TALLOC_FREE(frag);
2251                 if (req) {
2252                         tevent_req_nterror(req, status);
2253                 }
2254                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2255                 return;
2256         }
2257
2258         /* we free subreq after tstream_cli_np_use_trans */
2259         TALLOC_FREE(subreq);
2260
2261         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2262         if (!NT_STATUS_IS_OK(status)) {
2263                 TALLOC_FREE(frag);
2264                 if (req) {
2265                         tevent_req_nterror(req, status);
2266                 }
2267                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2268                 return;
2269         }
2270 }
2271
2272 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2273 {
2274         struct dcerpc_do_request_out_frag *frag =
2275                 tevent_req_callback_data(subreq,
2276                 struct dcerpc_do_request_out_frag);
2277         struct tevent_req *req = frag->req;
2278         NTSTATUS status;
2279         int ret;
2280         int sys_errno;
2281
2282         /*
2283          * If the caller has been free'ed, we have should
2284          * ignore any errors and just free 'frag'
2285          */
2286         if (req) {
2287                 struct dcerpc_do_request_state *state =
2288                         tevent_req_data(req,
2289                         struct dcerpc_do_request_state);
2290
2291                 state->out_frag = NULL;
2292         }
2293
2294         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2295         TALLOC_FREE(subreq);
2296         if (ret == -1) {
2297                 TALLOC_FREE(frag);
2298                 status = map_nt_error_from_unix_common(sys_errno);
2299                 if (req) {
2300                         tevent_req_nterror(req, status);
2301                 }
2302                 return;
2303         }
2304
2305         if (frag->subreq_wait2 != NULL) {
2306                 return;
2307         }
2308
2309         if (frag->is_last) {
2310                 TALLOC_FREE(frag);
2311                 return;
2312         }
2313         TALLOC_FREE(frag);
2314
2315         if (req == NULL) {
2316                 return;
2317         }
2318
2319         dcerpc_do_request_out_frag_next(req, NULL);
2320 }
2321
2322 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2323 {
2324         struct dcerpc_do_request_out_frag *frag =
2325                 tevent_req_callback_data(subreq,
2326                 struct dcerpc_do_request_out_frag);
2327         struct tevent_req *req = frag->req;
2328         NTSTATUS status;
2329         bool ok;
2330
2331         frag->subreq_wait2 = NULL;
2332
2333         ok = tevent_queue_wait_recv(subreq);
2334         if (!ok) {
2335                 status = NT_STATUS_INTERNAL_ERROR;
2336                 TALLOC_FREE(frag);
2337                 if (req) {
2338                         tevent_req_nterror(req, status);
2339                 }
2340                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2341                 return;
2342         }
2343
2344         TALLOC_FREE(subreq);
2345
2346         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2347         if (!NT_STATUS_IS_OK(status)) {
2348                 TALLOC_FREE(frag);
2349                 if (req) {
2350                         tevent_req_nterror(req, status);
2351                 }
2352                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2353                 return;
2354         }
2355
2356         TALLOC_FREE(frag);
2357
2358         /* we need to wait for incoming pdus */
2359 }
2360
2361 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
2362                                                  struct ncacn_packet *pkt,
2363                                                  DATA_BLOB frag)
2364 {
2365         struct tevent_req *req =
2366                 talloc_get_type_abort(private_data,
2367                 struct tevent_req);
2368         struct dcerpc_do_request_state *state =
2369                 tevent_req_data(req,
2370                 struct dcerpc_do_request_state);
2371         NTSTATUS error;
2372         NTSTATUS status;
2373         size_t pad_len = 0;
2374         DATA_BLOB payload;
2375         size_t new_total;
2376         size_t missing;
2377         bool ok;
2378
2379         /* Ensure we have the correct type. */
2380         switch (pkt->ptype) {
2381         case DCERPC_PKT_RESPONSE:
2382
2383                 /* Here's where we deal with incoming sign/seal. */
2384                 error = dcerpc_check_pdu_auth(state->call->sec,
2385                                         pkt,
2386                                         &pkt->u.response.stub_and_verifier,
2387                                         DCERPC_RESPONSE_LENGTH,
2388                                         &frag, &pad_len);
2389                 if (!NT_STATUS_IS_OK(error)) {
2390                         return error;
2391                 }
2392
2393                 if (!state->got_first) {
2394                         state->got_first = true;
2395
2396                         if (pkt->drep[0] & DCERPC_DREP_LE) {
2397                                 state->response.bigendian = false;
2398                         } else {
2399                                 state->response.bigendian = true;
2400                         }
2401
2402                         if (state->verify_bitmask1) {
2403                                 state->call->sec->verified_bitmask1 = true;
2404                         }
2405
2406                         if (state->verify_pcontext) {
2407                                 state->call->pres->verified_pcontext = true;
2408                         }
2409                 }
2410
2411                 if (state->response.bigendian) {
2412                         if (pkt->drep[0] != 0) {
2413                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2414                         }
2415                 } else {
2416                         if (pkt->drep[0] != DCERPC_DREP_LE) {
2417                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2418                         }
2419                 }
2420                 if (pkt->drep[1] != 0) {
2421                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2422                 }
2423                 if (pkt->drep[2] != 0) {
2424                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2425                 }
2426                 if (pkt->drep[3] != 0) {
2427                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2428                 }
2429
2430                 if (pkt->u.response.context_id != state->call->pres->context_id) {
2431                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2432                 }
2433
2434                 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2435                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2436                 }
2437 //TODO
2438                 /* Point the return values at the NDR data. */
2439                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2440
2441                 if (pkt->auth_length) {
2442                         /* We've already done integer wrap tests in
2443                          * dcerpc_check_auth(). */
2444                         payload.length = frag.length
2445                                          - DCERPC_RESPONSE_LENGTH
2446                                          - pad_len
2447                                          - DCERPC_AUTH_TRAILER_LENGTH
2448                                          - pkt->auth_length;
2449                 } else {
2450                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2451                 }
2452
2453                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2454                            (long unsigned int)frag.length,
2455                            (long unsigned int)payload.length,
2456                            (unsigned int)pad_len));
2457
2458                 /*
2459                  * If this is the first reply, and the allocation hint is
2460                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
2461                  * correct size.
2462                  */
2463
2464                 if ((state->response.blob.length == 0) &&
2465                     pkt->u.response.alloc_hint &&
2466                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
2467                         ok = data_blob_realloc(state, &state->response.blob,
2468                                                pkt->u.response.alloc_hint);
2469                         if (!ok) {
2470                                 DEBUG(0, ("reply alloc hint %d too "
2471                                           "large to allocate\n",
2472                                     (int)pkt->u.response.alloc_hint));
2473                                 return NT_STATUS_NO_MEMORY;
2474                         }
2475                 }
2476
2477                 new_total = state->response.ofs + payload.length;
2478
2479                 if (new_total > 15 * 1024 *1024) {
2480                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2481                 }
2482
2483                 missing = new_total - state->response.blob.length;
2484
2485                 if (missing > 0) {
2486                         ok = data_blob_realloc(state, &state->response.blob,
2487                                                new_total);
2488                         if (!ok) {
2489                                 DEBUG(0, ("reply alloc hint %d too "
2490                                           "large to allocate\n",
2491                                     (int)pkt->u.response.alloc_hint));
2492                                 return NT_STATUS_NO_MEMORY;
2493                         }
2494                 }
2495
2496                 memcpy(state->response.blob.data + state->response.ofs,
2497                        payload.data, payload.length);
2498                 state->response.ofs += payload.length;
2499
2500                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2501                         tevent_req_done(req);//TODO
2502                         return NT_STATUS_OK;
2503                 }
2504
2505                 return dcerpc_connection_loop_restart(state->conn, state->ev);
2506
2507         case DCERPC_PKT_FAULT:
2508
2509                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2510                           "code %s received from %s!\n",
2511                           dcerpc_errstr(talloc_tos(),
2512                           pkt->u.fault.status),
2513                           "TODO"));
2514
2515                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2516                 if (NT_STATUS_IS_OK(status)) {
2517                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
2518                 }
2519
2520                 tevent_req_nterror(req, status);//TODO
2521                 return NT_STATUS_OK;
2522         default:
2523                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2524                           (unsigned int)pkt->ptype,
2525                          "TODO"));
2526                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2527         }
2528 }
2529
2530 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2531                                 TALLOC_CTX *mem_ctx,
2532                                 DATA_BLOB *response,
2533                                 bool *bigendian)
2534 {
2535         struct dcerpc_do_request_state *state =
2536                 tevent_req_data(req,
2537                 struct dcerpc_do_request_state);
2538         NTSTATUS status;
2539
2540         if (tevent_req_is_nterror(req, &status)) {
2541                 tevent_req_received(req);
2542                 return status;
2543         }
2544
2545         /* return data to caller and assign it ownership of memory */
2546         response->data = talloc_move(mem_ctx, &state->response.blob.data);
2547         response->length = state->response.blob.length;
2548         *bigendian = state->response.bigendian;
2549
2550         tevent_req_received(req);
2551         return NT_STATUS_OK;
2552 }