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