STEP01x: dcerpc_submit_shutdown
[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 struct dcerpc_server;
39 struct dcerpc_context_handle;
40
41 struct dcerpc_association {
42         uint32_t assoc_group_id;
43         uint16_t client_features;
44         uint16_t features;
45         bool negotiate_done;
46         uint32_t next_call_id;
47
48         size_t num_context_handles;
49         struct db_context *context_handles;
50 };
51
52 struct dcerpc_connection {
53         struct dcerpc_association *assoc;
54
55         struct {
56                 struct tstream_context *stream;
57                 dcerpc_connection_use_trans_fn use_trans_fn;
58                 struct tevent_queue *write_queue;
59         } transport;
60
61         struct {
62                 uint16_t max_xmit_frag;
63                 uint16_t max_recv_frag;
64                 bool concurrent_multiplex;
65                 bool bind_done;
66         } features;
67
68         uint32_t next_sec_context_id;
69         uint16_t next_pres_context_id;
70
71         struct {
72                 struct tevent_queue *out_queue;
73                 struct dcerpc_call *list;
74                 struct dcerpc_call *active;
75                 struct dcerpc_call *new_call;
76         } calls;
77
78         struct {
79                 struct tevent_context *ev;
80                 struct tevent_req *subreq;
81         } loop;
82 };
83
84 struct dcerpc_security {
85         uint32_t context_id;
86         enum dcerpc_AuthType auth_type;
87         enum dcerpc_AuthLevel auth_level;
88         struct gensec_security *gensec;
89         struct auth_session_info *session_info;
90         DATA_BLOB session_key;
91         bool client_hdr_signing;
92         bool hdr_signing;
93         bool verified_bitmask1;
94 };
95
96 struct dcerpc_presentation {
97         uint16_t context_id;
98         const struct ndr_interface_table *table;
99         struct ndr_syntax_id transfer;
100         struct {
101                 struct dcerpc_ctx_list req;
102                 struct dcerpc_ack_ctx ack;
103         } negotiate;
104         bool verified_pcontext;
105 };
106
107 struct dcerpc_call {
108         struct dcerpc_call *prev, *next;
109         uint32_t call_id;
110
111         struct dcerpc_security *sec;
112         struct dcerpc_presentation *pres;
113
114         struct {
115                 struct tevent_req *req;
116                 NTSTATUS (*handler)(struct tevent_req *req,
117                                     struct ncacn_packet *pkt,
118                                     DATA_BLOB frag);
119         } incoming;
120 };
121
122 struct dcerpc_object_handle {
123
124 };
125
126 struct dcerpc_context_handle {
127         struct dcerpc_association *assoc;
128
129         struct policy_handle wire;
130
131         void *ptr;
132 };
133
134 struct dcerpc_server_auth_info;
135
136 struct dcerpc_server {
137         struct {
138
139         };
140 };
141
142 struct dcerpc_server_auth_info {
143         struct dcerpc_server_auth_info *prev, *next;
144         enum dcerpc_AuthType auth_type;
145         enum dcerpc_AuthType min_auth_level;
146         const char *principal;
147         struct cli_credentials *creds;
148 };
149
150 struct dcerpc_server_manager {
151         const struct ndr_interface_table *table;
152
153 };
154
155 struct dcerpc_server_endpoint {
156         struct dcerpc_server_endpoint *prev, *next;
157
158         const struct dcerpc_binding *binding;
159 };
160
161 struct dcerpc_call_handle;
162
163 typedef struct tevent_req *(*dcerpc_call_entry_point_send_fn_t)(TALLOC_CTX *mem_ctx,
164                                                         struct tevent_context *ev,
165                                                         struct dcerpc_call_handle *call,
166                                                         void *r);
167 typedef NTSTATUS (*dcerpc_call_entry_point_recv_fn_t)(struct tevent_req *req);
168
169 struct dcerpc_call_entry_point_fns {
170         dcerpc_call_entry_point_send_fn_t fn_send;
171         dcerpc_call_entry_point_recv_fn_t fn_recv;
172 };
173
174 struct dcerpc_call_entry_point_vector {
175         const char *name;
176         const struct ndr_interface_table *table;
177         uint32_t num_fns;
178         const struct dcerpc_call_entry_point_fns *fns;
179 };
180
181 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
182                                                      uint16_t client_features)
183 {
184         struct dcerpc_association *assoc;
185
186         assoc = talloc_zero(mem_ctx, struct dcerpc_association);
187         if (assoc == NULL) {
188                 return NULL;
189         }
190
191         assoc->next_call_id = 1;
192
193         assoc->client_features = client_features;
194
195         return assoc;
196 }
197
198 static int dcerpc_connection_destructor(struct dcerpc_connection *conn);
199
200 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
201                                         struct dcerpc_association *assoc,
202                                         struct tstream_context **stream)
203 {
204         struct dcerpc_connection *conn;
205
206         conn = talloc_zero(mem_ctx, struct dcerpc_connection);
207         if (conn == NULL) {
208                 return NULL;
209         }
210         conn->assoc = assoc;
211
212         conn->transport.stream = talloc_move(conn, stream);
213         conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
214         if (conn->transport.write_queue == NULL) {
215                 talloc_free(conn);
216                 return NULL;
217         }
218
219         conn->features.max_xmit_frag = UINT16_MAX;
220         conn->features.max_recv_frag = UINT16_MAX;
221
222         conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
223         if (conn->calls.out_queue == NULL) {
224                 talloc_free(conn);
225                 return NULL;
226         }
227
228         talloc_set_destructor(conn, dcerpc_connection_destructor);
229
230         return conn;
231 }
232
233 void dcerpc_connection_set_max_fragment_sizes(struct dcerpc_connection *conn,
234                                               uint16_t max_size)
235 {
236         conn->features.max_xmit_frag = max_size;
237         conn->features.max_recv_frag = max_size;
238 }
239
240 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
241                                         dcerpc_connection_use_trans_fn fn)
242 {
243         conn->transport.use_trans_fn = fn;
244 }
245
246 bool dcerpc_connection_is_connected(const struct dcerpc_connection *conn)
247 {
248         if (conn == NULL) {
249                 return false;
250         }
251
252         if (conn->transport.stream == NULL) {
253                 return false;
254         }
255
256         return true;
257 }
258
259 static void dcerpc_connection_dead(struct dcerpc_connection *conn,
260                                    NTSTATUS error)
261 {
262         struct dcerpc_call *call = NULL;
263
264         if (conn == NULL) {
265                 return;
266         }
267
268         if (conn->transport.stream == NULL) {
269                 return;
270         }
271
272         tevent_queue_stop(conn->transport.write_queue);
273         tevent_queue_stop(conn->calls.out_queue);
274         TALLOC_FREE(conn->loop.subreq);
275         TALLOC_FREE(conn->transport.stream);
276
277         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, error)) {
278                 error = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
279         }
280
281         if (NT_STATUS_EQUAL(NT_STATUS_OK, error)) {
282                 error = NT_STATUS_LOCAL_DISCONNECT;
283         }
284
285         if (conn->calls.active != NULL) {
286                 DLIST_PROMOTE(conn->calls.list, conn->calls.active);
287         }
288
289         if (conn->calls.new_call != NULL) {
290                 DLIST_ADD_END(conn->calls.list, conn->calls.new_call, NULL);
291                 conn->calls.new_call = NULL;
292         }
293
294         for (call = conn->calls.list; call; call = call->next) {
295                 if (call->incoming.req == NULL) {
296                         continue;
297                 }
298
299                 /*
300                  * the request was already prepared with
301                  * tevent_req_defer_callback().
302                  */
303                 tevent_req_nterror(call->incoming.req, error);
304         }
305 }
306
307 static int dcerpc_connection_destructor(struct dcerpc_connection *conn)
308 {
309         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
310         return 0;
311 }
312
313 struct dcerpc_security *dcerpc_security_allocate(
314                                         TALLOC_CTX *mem_ctx,
315                                         struct dcerpc_connection *conn,
316                                         enum dcerpc_AuthType auth_type,
317                                         enum dcerpc_AuthLevel auth_level,
318                                         struct gensec_security **gensec)
319 {
320         struct dcerpc_security *sec;
321
322         sec = talloc_zero(mem_ctx, struct dcerpc_security);
323         if (sec == NULL) {
324                 return NULL;
325         }
326
327         sec->context_id = conn->next_sec_context_id++;
328         sec->auth_type = auth_type;
329         sec->auth_level = auth_level;
330
331         if (gensec != NULL) {
332                 sec->gensec = talloc_move(sec, gensec);
333         }
334
335         return sec;
336 }
337
338 void dcerpc_security_get_auth_info(const struct dcerpc_security *sec,
339                                    enum dcerpc_AuthType *auth_type,
340                                    enum dcerpc_AuthLevel *auth_level)
341 {
342         enum dcerpc_AuthType _auth_type;
343         enum dcerpc_AuthLevel _auth_level;
344
345         if (auth_type == NULL) {
346                 auth_type = &_auth_type;
347         }
348
349         if (auth_level == NULL) {
350                 auth_level = &_auth_level;
351         }
352
353         if (sec == NULL) {
354                 *auth_type = DCERPC_AUTH_TYPE_NONE;
355                 *auth_level = DCERPC_AUTH_LEVEL_NONE;
356                 return;
357         }
358
359         *auth_type = sec->auth_type;
360         *auth_level = sec->auth_level;
361 }
362
363 struct dcerpc_presentation *dcerpc_presentation_allocate(
364                                         TALLOC_CTX *mem_ctx,
365                                         struct dcerpc_connection *conn,
366                                         const struct ndr_interface_table *table,
367                                         const struct ndr_syntax_id *transfer)
368 {
369         struct dcerpc_presentation *pres;
370
371         pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
372         if (pres == NULL) {
373                 return NULL;
374         }
375
376         pres->context_id = conn->next_pres_context_id++;
377         pres->table = table;
378         pres->transfer = *transfer;
379
380         pres->negotiate.req.abstract_syntax = table->syntax_id;
381         pres->negotiate.req.context_id = pres->context_id;
382         pres->negotiate.req.num_transfer_syntaxes = 1;
383         pres->negotiate.req.transfer_syntaxes = &pres->transfer;
384
385         pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
386         pres->negotiate.ack.reason.value =
387                 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
388
389         return pres;
390 }
391
392 struct dcerpc_presentation *dcerpc_presentation_test_copy(
393                                         TALLOC_CTX *mem_ctx,
394                                         const struct dcerpc_presentation *pres1,
395                                         const uint32_t *context_id,
396                                         const struct ndr_interface_table *table,
397                                         const struct ndr_syntax_id *transfer)
398 {
399         struct dcerpc_presentation *pres2;
400
401         pres2 = talloc_zero(mem_ctx, struct dcerpc_presentation);
402         if (pres2 == NULL) {
403                 return NULL;
404         }
405         *pres2 = *pres1;
406
407         if (context_id != NULL) {
408                 pres2->context_id = *context_id;
409         }
410         if (table != NULL) {
411                 pres2->table = table;
412         }
413         if (transfer != NULL) {
414                 pres2->transfer = *transfer;
415         }
416
417         pres2->negotiate.req.abstract_syntax = pres2->table->syntax_id;
418         pres2->negotiate.req.context_id = pres2->context_id;
419         pres2->negotiate.req.num_transfer_syntaxes = 1;
420         pres2->negotiate.req.transfer_syntaxes = &pres2->transfer;
421
422         pres2->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
423         pres2->negotiate.ack.reason.value =
424                 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
425
426         return pres2;
427 }
428
429 NTSTATUS dcerpc_presentation_status(const struct dcerpc_presentation *pres)
430 {
431         const struct dcerpc_ack_ctx *ack = &pres->negotiate.ack;
432
433         switch (ack->result) {
434         case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
435                 return NT_STATUS_OK;
436
437         case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
438                 /*
439                  * We have not asked for this...
440                  */
441                 return NT_STATUS_RPC_PROTOCOL_ERROR;
442         default:
443                 break;
444         }
445
446         switch (ack->reason.value) {
447         case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
448                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
449
450         case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
451                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
452
453         default:
454                 break;
455         }
456
457         return NT_STATUS_UNSUCCESSFUL;
458 }
459
460 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
461                                          struct dcerpc_association *assoc,
462                                          struct dcerpc_security *sec,
463                                          struct dcerpc_presentation *pres)
464 {
465         struct dcerpc_call *call;
466
467         call = talloc_zero(mem_ctx, struct dcerpc_call);
468         if (call == NULL) {
469                 return NULL;
470         }
471
472         call->call_id = assoc->next_call_id++;
473
474         call->sec = sec;
475         call->pres = pres;
476
477         return call;
478 }
479
480 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
481                                        size_t header_len,
482                                        size_t data_left,
483                                        size_t max_xmit_frag,
484                                        size_t pad_alignment,
485                                        size_t *data_to_send,
486                                        size_t *frag_len,
487                                        size_t *auth_len,
488                                        size_t *pad_len)
489 {
490         size_t max_len;
491         size_t mod_len;
492
493         /* no auth token cases first */
494         switch (sec->auth_level) {
495         case DCERPC_AUTH_LEVEL_NONE:
496         case DCERPC_AUTH_LEVEL_CONNECT:
497         case DCERPC_AUTH_LEVEL_PACKET:
498                 max_len = max_xmit_frag - header_len;
499                 *data_to_send = MIN(max_len, data_left);
500                 *pad_len = 0;
501                 *auth_len = 0;
502                 *frag_len = header_len + *data_to_send;
503                 return NT_STATUS_OK;
504
505         case DCERPC_AUTH_LEVEL_PRIVACY:
506         case DCERPC_AUTH_LEVEL_INTEGRITY:
507                 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
508                         return NT_STATUS_INVALID_PARAMETER_MIX;
509                 }
510                 if (sec->gensec == NULL) {
511                         return NT_STATUS_INVALID_PARAMETER_MIX;
512                 }
513                 break;
514
515         default:
516                 return NT_STATUS_INVALID_PARAMETER;
517         }
518
519
520         /* Sign/seal case, calculate auth and pad lengths */
521
522         max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
523
524         *auth_len = gensec_sig_size(sec->gensec, max_len);
525
526         max_len -= *auth_len;
527
528         *data_to_send = MIN(max_len, data_left);
529
530         mod_len = (*data_to_send) % pad_alignment;
531         if (mod_len) {
532                 *pad_len = pad_alignment - mod_len;
533         } else {
534                 *pad_len = 0;
535         }
536
537         if (*data_to_send + *pad_len > max_len) {
538                 *data_to_send -= pad_alignment;
539         }
540
541         *frag_len = header_len + *data_to_send + *pad_len
542                         + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
543
544         return NT_STATUS_OK;
545 }
546
547 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
548                                        TALLOC_CTX *mem_ctx,
549                                        struct ncacn_packet *pkt,
550                                        struct dcerpc_auth *auth_info)
551 {
552         struct ndr_push *ndr;
553         enum ndr_err_code ndr_err;
554
555         ndr = ndr_push_init_ctx(mem_ctx);
556         if (!ndr) {
557                 return NT_STATUS_NO_MEMORY;
558         }
559
560         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
561                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
562         }
563
564         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
565                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
566         }
567
568         if (auth_info) {
569                 pkt->auth_length = auth_info->credentials.length;
570         } else {
571         //      pkt->auth_length = 0;
572         }
573
574         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
575         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
576                 return ndr_map_error2ntstatus(ndr_err);
577         }
578
579         if (auth_info) {
580 #if 0
581                 /* the s3 rpc server doesn't handle auth padding in
582                    bind requests. Use zero auth padding to keep us
583                    working with old servers */
584                 uint32_t offset = ndr->offset;
585                 ndr_err = ndr_push_align(ndr, 16);
586                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
587                         return ndr_map_error2ntstatus(ndr_err);
588                 }
589                 auth_info->auth_pad_length = ndr->offset - offset;
590 #else
591                 auth_info->auth_pad_length = 0;
592 #endif
593                 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
594                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
595                         return ndr_map_error2ntstatus(ndr_err);
596                 }
597         }
598
599         *blob = ndr_push_blob(ndr);
600
601         /* fill in the frag length */
602         dcerpc_set_frag_length(blob, blob->length);
603
604         return NT_STATUS_OK;
605 }
606
607 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
608                                          enum dcerpc_pkt_type ptype,
609                                          uint8_t pfc_flags,
610                                          uint16_t auth_length,
611                                          uint32_t call_id,
612                                          union dcerpc_payload *u,
613                                          DATA_BLOB *blob)
614 {
615         struct ncacn_packet r;
616         NTSTATUS status;
617
618         r.rpc_vers              = 5;
619         r.rpc_vers_minor        = 0;
620         r.ptype                 = ptype;
621         r.pfc_flags             = pfc_flags;
622         r.drep[0]               = DCERPC_DREP_LE;
623         r.drep[1]               = 0;
624         r.drep[2]               = 0;
625         r.drep[3]               = 0;
626         r.auth_length           = auth_length;
627         r.call_id               = call_id;
628         r.u                     = *u;
629
630         status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
631         if (!NT_STATUS_IS_OK(status)) {
632                 return status;
633         }
634
635         if (DEBUGLEVEL >= 10) {
636                 /* set frag len for print function */
637                 r.frag_length = blob->length;
638                 NDR_PRINT_DEBUG(ncacn_packet, &r);
639         }
640
641         return NT_STATUS_OK;
642 }
643
644 #define DCERPC_PAYLOAD_PADDING_SIZE 16
645
646 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
647                                  enum dcerpc_AuthType auth_type,
648                                  enum dcerpc_AuthLevel auth_level,
649                                  uint8_t auth_pad_length,
650                                  uint32_t auth_context_id,
651                                  const DATA_BLOB *credentials,
652                                  DATA_BLOB *blob)
653 {
654         struct dcerpc_auth r;
655         enum ndr_err_code ndr_err;
656
657         r.auth_type             = auth_type;
658         r.auth_level            = auth_level;
659         r.auth_pad_length       = auth_pad_length;
660         r.auth_reserved         = 0;
661         r.auth_context_id       = auth_context_id;
662         r.credentials           = *credentials;
663
664         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
665                 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
666         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
667                 return ndr_map_error2ntstatus(ndr_err);
668         }
669
670         if (DEBUGLEVEL >= 10) {
671                 NDR_PRINT_DEBUG(dcerpc_auth, &r);
672         }
673
674         return NT_STATUS_OK;
675 }
676
677 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
678                                           size_t pad_len,
679                                           size_t auth_len,
680                                           DATA_BLOB *rpc_out)
681 {
682         char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
683         DATA_BLOB auth_info;
684         DATA_BLOB auth_blob;
685         uint16_t data_and_pad_len = 0;
686         NTSTATUS status;
687
688         if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
689                 return NT_STATUS_INVALID_PARAMETER_MIX;
690         }
691
692         if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
693             sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
694                 return NT_STATUS_OK;
695         }
696
697         if (sec->gensec == NULL) {
698                 return NT_STATUS_INVALID_PARAMETER_MIX;
699         }
700
701         if (pad_len) {
702                 /* Copy the sign/seal padding data. */
703                 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
704                         return NT_STATUS_NO_MEMORY;
705                 }
706         }
707
708         data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
709
710         /* marshall the dcerpc_auth with an actually empty auth_blob.
711          * This is needed because the ntmlssp signature includes the
712          * auth header. We will append the actual blob later. */
713         auth_blob = data_blob_null;
714         status = dcerpc_auth_blob(rpc_out->data,
715                                   sec->auth_type,
716                                   sec->auth_level,
717                                   pad_len,
718                                   sec->context_id,
719                                   &auth_blob,
720                                   &auth_info);
721         if (!NT_STATUS_IS_OK(status)) {
722                 return status;
723         }
724
725         /* append the header */
726         if (!data_blob_append(NULL, rpc_out,
727                                 auth_info.data, auth_info.length)) {
728                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
729                           (unsigned int)auth_info.length));
730                 return NT_STATUS_NO_MEMORY;
731         }
732         data_blob_free(&auth_info);
733
734         switch (sec->auth_level) {
735         case DCERPC_AUTH_LEVEL_PRIVACY:
736                 /* Data portion is encrypted. */
737                 status = gensec_seal_packet(sec->gensec,
738                                             rpc_out->data,
739                                             rpc_out->data
740                                             + DCERPC_RESPONSE_LENGTH,
741                                             data_and_pad_len,
742                                             rpc_out->data,
743                                             rpc_out->length,
744                                             &auth_blob);
745                 if (!NT_STATUS_IS_OK(status)) {
746                         return status;
747                 }
748                 break;
749
750         case DCERPC_AUTH_LEVEL_INTEGRITY:
751                 /* Data is signed. */
752                 status = gensec_sign_packet(sec->gensec,
753                                             rpc_out->data,
754                                             rpc_out->data
755                                             + DCERPC_RESPONSE_LENGTH,
756                                             data_and_pad_len,
757                                             rpc_out->data,
758                                             rpc_out->length,
759                                             &auth_blob);
760                 if (!NT_STATUS_IS_OK(status)) {
761                         return status;
762                 }
763                 break;
764
765         default:
766                 /* Can't happen. */
767                 smb_panic("bad auth level");
768                 /* Notreached. */
769                 return NT_STATUS_INVALID_PARAMETER_MIX;
770         }
771
772         if (auth_blob.length != auth_len) {
773                 return NT_STATUS_INVALID_PARAMETER_MIX;
774         }
775
776         /* Finally attach the blob. */
777         if (!data_blob_append(NULL, rpc_out,
778                                 auth_blob.data, auth_blob.length)) {
779                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
780                           (unsigned int)auth_blob.length));
781                 return NT_STATUS_NO_MEMORY;
782         }
783         data_blob_free(&auth_blob);
784
785         return NT_STATUS_OK;
786 }
787
788 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
789                            struct ncacn_packet *pkt,
790                            DATA_BLOB *pkt_trailer,
791                            size_t header_size,
792                            DATA_BLOB *raw_pkt,
793                            size_t *pad_len)
794 {
795         NTSTATUS status;
796         struct dcerpc_auth auth_info;
797         uint32_t auth_length;
798         DATA_BLOB full_pkt;
799         DATA_BLOB data;
800
801         switch (sec->auth_level) {
802         case DCERPC_AUTH_LEVEL_PRIVACY:
803                 DEBUG(10, ("Requested Privacy.\n"));
804                 break;
805
806         case DCERPC_AUTH_LEVEL_INTEGRITY:
807                 DEBUG(10, ("Requested Integrity.\n"));
808                 break;
809
810         case DCERPC_AUTH_LEVEL_CONNECT:
811                 if (pkt->auth_length != 0) {
812                         break;
813                 }
814                 *pad_len = 0;
815                 return NT_STATUS_OK;
816
817         case DCERPC_AUTH_LEVEL_NONE:
818                 if (pkt->auth_length != 0) {
819                         DEBUG(3, ("Got non-zero auth len on non "
820                                   "authenticated connection!\n"));
821                         return NT_STATUS_INVALID_PARAMETER;
822                 }
823                 *pad_len = 0;
824                 return NT_STATUS_OK;
825
826         default:
827                 DEBUG(3, ("Unimplemented Auth Level %d",
828                           sec->auth_level));
829                 return NT_STATUS_INVALID_PARAMETER;
830         }
831
832         /* Paranioa checks for auth_length. */
833         if (pkt->auth_length > pkt->frag_length) {
834                 return NT_STATUS_INFO_LENGTH_MISMATCH;
835         }
836         if (((unsigned int)pkt->auth_length
837              + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
838             ((unsigned int)pkt->auth_length
839              + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
840                 /* Integer wrap attempt. */
841                 return NT_STATUS_INFO_LENGTH_MISMATCH;
842         }
843
844         status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
845                                           &auth_info, &auth_length, false);
846         if (!NT_STATUS_IS_OK(status)) {
847                 return status;
848         }
849
850         if (auth_info.auth_type != sec->auth_type) {
851                 return NT_STATUS_RPC_PROTOCOL_ERROR;
852         }
853
854         if (auth_info.auth_level != sec->auth_level) {
855                 return NT_STATUS_RPC_PROTOCOL_ERROR;
856         }
857
858         if (auth_info.auth_context_id != sec->context_id) {
859                 return NT_STATUS_RPC_PROTOCOL_ERROR;
860         }
861
862         data = data_blob_const(raw_pkt->data + header_size,
863                                 pkt_trailer->length - auth_length);
864         full_pkt = data_blob_const(raw_pkt->data,
865                                 raw_pkt->length - auth_info.credentials.length);
866
867         switch (sec->auth_type) {
868         case DCERPC_AUTH_TYPE_NONE:
869         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
870                 return NT_STATUS_OK;
871         default:
872                 break;
873         }
874
875         switch (sec->auth_level) {
876         case DCERPC_AUTH_LEVEL_PRIVACY:
877                 /* Data portion is encrypted. */
878                 status = gensec_unseal_packet(sec->gensec,
879                                             data.data,
880                                             data.length,
881                                             full_pkt.data,
882                                             full_pkt.length,
883                                             &auth_info.credentials);
884                 if (!NT_STATUS_IS_OK(status)) {
885                         return status;
886                 }
887                 break;
888
889         case DCERPC_AUTH_LEVEL_INTEGRITY:
890                 /* Data is signed. */
891                 status = gensec_check_packet(sec->gensec,
892                                             data.data,
893                                             data.length,
894                                             full_pkt.data,
895                                             full_pkt.length,
896                                             &auth_info.credentials);
897                 if (!NT_STATUS_IS_OK(status)) {
898                         return status;
899                 }
900                 break;
901         default:
902                 return NT_STATUS_INVALID_PARAMETER;
903         }
904         /* TODO: remove later
905          * this is still needed because in the server code the
906          * pkt_trailer actually has a copy of the raw data, and they
907          * are still both used in later calls */
908         if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
909                 memcpy(pkt_trailer->data, data.data, data.length);
910         }
911
912         *pad_len = auth_info.auth_pad_length;
913         data_blob_free(&auth_info.credentials);
914         return NT_STATUS_OK;
915 }
916
917 static void dcerpc_connection_loop(struct tevent_req *subreq);
918
919 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
920                                                struct tevent_context *ev)
921 {
922         if (ev == NULL) {
923                 return NT_STATUS_INVALID_PARAMETER; // TODO...
924         }
925
926         if (conn->loop.subreq) {
927                 if (conn->loop.ev != ev) {
928                         return NT_STATUS_INVALID_PARAMETER; // TODO...
929                 }
930                 return NT_STATUS_OK;
931         }
932
933         if (conn->calls.list == NULL) {
934                 conn->loop.ev = NULL;
935                 return NT_STATUS_OK;
936         }
937
938         conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
939                                                           ev,
940                                                           conn->transport.stream);
941         if (conn->loop.subreq == NULL) {
942                 return NT_STATUS_NO_MEMORY;
943         }
944         tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
945         conn->loop.ev = ev;
946         return NT_STATUS_OK;
947 }
948
949 static void dcerpc_connection_loop(struct tevent_req *subreq)
950 {
951         struct dcerpc_connection *conn =
952                 tevent_req_callback_data(subreq,
953                 struct dcerpc_connection);
954         NTSTATUS error;
955         struct ncacn_packet *pkt;
956         DATA_BLOB pdu;
957         struct dcerpc_call *call;
958         bool valid_type = false;
959         bool allow_fragments = false;
960         bool allow_newcall = false;
961         bool allow_ignore = false;
962
963         conn->loop.subreq = NULL;
964
965         error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
966         if (!NT_STATUS_IS_OK(error)) {
967                 TALLOC_FREE(subreq);
968                 dcerpc_connection_dead(conn, error);
969                 return;
970         }
971
972         if (DEBUGLEVEL >= 10) {
973                 NDR_PRINT_DEBUG(ncacn_packet, pkt);
974         }
975
976         switch (pkt->ptype) {
977         case DCERPC_PKT_REQUEST:
978                 /* Ordinary request. */
979                 valid_type = true;
980                 allow_fragments = true;
981                 allow_newcall = true;
982                 break;
983
984         case DCERPC_PKT_PING:
985                 /* Connectionless is server alive ? */
986                 break;
987
988         case DCERPC_PKT_RESPONSE:
989                 /* Ordinary reply. */
990                 valid_type = true;
991                 allow_fragments = true;
992                 break;
993
994         case DCERPC_PKT_FAULT:
995                 /* Fault in processing of call. */
996                 valid_type = true;
997                 break;
998
999         case DCERPC_PKT_WORKING:
1000                 /* Connectionless reply to a ping when server busy. */
1001                 break;
1002
1003         case DCERPC_PKT_NOCALL:
1004                 /* Connectionless reply to a ping when server has lost part of clients call. */
1005                 break;
1006
1007         case DCERPC_PKT_REJECT:
1008                 /* Refuse a request with a code. */
1009                 break;
1010
1011         case DCERPC_PKT_ACK:
1012                 break;
1013
1014         case DCERPC_PKT_CL_CANCEL:
1015                 break;
1016
1017         case DCERPC_PKT_FACK:
1018                 break;
1019
1020         case DCERPC_PKT_CANCEL_ACK:
1021                 /* Server ACK to client cancel request. */
1022                 break;
1023
1024         case DCERPC_PKT_BIND:
1025                 /* Bind to interface. */
1026                 valid_type = true;
1027                 allow_newcall = true;
1028                 break;
1029
1030         case DCERPC_PKT_BIND_ACK:
1031                 /* Server ack of bind. */
1032                 valid_type = true;
1033                 break;
1034
1035         case DCERPC_PKT_BIND_NAK:
1036                 /* Server nack of bind. */
1037                 valid_type = true;
1038                 break;
1039
1040         case DCERPC_PKT_ALTER:
1041                 /* Alter auth. */
1042                 valid_type = true;
1043                 allow_newcall = true;
1044                 break;
1045
1046         case DCERPC_PKT_ALTER_RESP:
1047                 /* Reply to alter auth. */
1048                 valid_type = true;
1049                 break;
1050
1051         case DCERPC_PKT_AUTH3:
1052                 /* Auth3 request */
1053                 valid_type = true;
1054                 allow_newcall = true;
1055                 break;
1056
1057         case DCERPC_PKT_SHUTDOWN:
1058                 /* Server to client request to shutdown. */
1059                 valid_type = true;
1060                 break;
1061
1062         case DCERPC_PKT_CO_CANCEL:
1063                 /* Connection-oriented cancel request. */
1064                 valid_type = true;
1065                 allow_ignore = true;
1066                 break;
1067
1068         case DCERPC_PKT_ORPHANED:
1069                 /*
1070                  * Client telling server it's aborting a partially sent request
1071                  * or telling server to stop sending replies.
1072                  */
1073                 valid_type = true;
1074                 allow_ignore = true;
1075                 break;
1076
1077         case DCERPC_PKT_RTS:
1078                 /* RTS packets used in ncacn_http */
1079                 break;
1080         }
1081
1082         if (!valid_type) {
1083                 TALLOC_FREE(subreq);
1084                 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1085                 return;
1086         }
1087
1088         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1089                 if (!allow_fragments) {
1090                         TALLOC_FREE(subreq);
1091                         dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1092                         return;
1093                 }
1094         }
1095
1096         if (conn->calls.active != NULL) {
1097
1098                 if (pkt->call_id != conn->calls.active->call_id) {
1099                         TALLOC_FREE(subreq);
1100                         dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1101                         return;
1102                 }
1103
1104                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1105                         TALLOC_FREE(subreq);
1106                         dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1107                         return;
1108                 }
1109
1110                 call = conn->calls.active;
1111
1112                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1113                         conn->calls.active = NULL;
1114                 }
1115         } else {
1116                 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1117                         TALLOC_FREE(subreq);
1118                         dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1119                         return;
1120                 }
1121
1122                 call = conn->calls.list;
1123         }
1124
1125         for (call = conn->calls.list; call; call = call->next) {
1126                 if (call->call_id == pkt->call_id) {
1127                         break;
1128                 }
1129         }
1130
1131         if (call == NULL && allow_newcall) {
1132                 call = conn->calls.new_call;
1133         }
1134
1135         if (call == NULL && allow_ignore) {
1136                 TALLOC_FREE(subreq);
1137                 goto may_restart;
1138         }
1139
1140         if (call == NULL) {
1141                 TALLOC_FREE(subreq);
1142                 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1143                 return;
1144         }
1145
1146         if (call->incoming.handler == NULL) {
1147                 TALLOC_FREE(subreq);
1148                 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1149                 return;
1150         }
1151
1152         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1153                 conn->calls.active = call;
1154
1155                 // TODO
1156                 //
1157                 // reassemble and return
1158         }
1159
1160         error = call->incoming.handler(call->incoming.req, pkt, pdu);
1161         TALLOC_FREE(subreq);
1162         if (!NT_STATUS_IS_OK(error)) {
1163                 dcerpc_connection_dead(conn, error);
1164                 return;
1165         }
1166
1167 may_restart:
1168         if (conn->calls.new_call == NULL) {
1169                 conn->loop.ev = NULL;
1170                 return;
1171         }
1172
1173         error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
1174         if (!NT_STATUS_IS_OK(error)) {
1175                 dcerpc_connection_dead(conn, error);
1176                 return;
1177         }
1178 }
1179
1180 struct dcerpc_do_bind_out_frag;
1181
1182 struct dcerpc_do_bind_state {
1183         struct tevent_context *ev;
1184         struct dcerpc_connection *conn;
1185         struct dcerpc_call *call;
1186         struct dcerpc_security *sec;
1187         bool proposed_hdr_signing;
1188         DATA_BLOB sec_in;
1189         NTSTATUS sec_status;
1190         DATA_BLOB sec_out;
1191         struct dcerpc_do_bind_out_frag *out_frag;
1192         uint32_t num_pres;
1193         struct dcerpc_presentation **pres;
1194         uint32_t remaining_pres;
1195
1196         uint32_t num_ctx;
1197         struct dcerpc_ctx_list *ctx_list;
1198         struct ndr_syntax_id features;
1199 };
1200
1201 struct dcerpc_do_bind_out_frag {
1202         struct tevent_context *ev;
1203         struct dcerpc_connection *conn;
1204         struct tevent_req *req;
1205         enum dcerpc_pkt_type ptype;
1206         DATA_BLOB blob;
1207         struct iovec vector;
1208         struct tevent_req *subreq_wait1;
1209         struct tevent_req *subreq_wait2;
1210 };
1211
1212 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1213                                    enum tevent_req_state req_state);
1214
1215 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
1216 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
1217
1218 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1219                                               struct ncacn_packet *pkt,
1220                                               DATA_BLOB frag);
1221
1222 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
1223                                 struct tevent_context *ev,
1224                                 struct dcerpc_connection *conn,
1225                                 struct dcerpc_call *call,
1226                                 struct dcerpc_security *sec,
1227                                 uint32_t num_pres,
1228                                 struct dcerpc_presentation **pres)
1229 {
1230         struct tevent_req *req;
1231         struct dcerpc_do_bind_state *state;
1232         struct tevent_req *subreq;
1233
1234         req = tevent_req_create(mem_ctx, &state,
1235                                 struct dcerpc_do_bind_state);
1236         if (req == NULL) {
1237                 return NULL;
1238         }
1239         state->ev = ev;
1240         state->conn = conn;
1241         state->call = call;
1242         state->sec = sec;
1243         state->remaining_pres = num_pres;
1244         state->num_pres = num_pres;
1245         state->pres = pres;
1246
1247         state->call->incoming.req = req;
1248         state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
1249         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1250         tevent_req_defer_callback(req, ev);
1251         tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
1252
1253         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1254                 subreq = gensec_update_send(state, ev,
1255                                             state->sec->gensec,
1256                                             state->sec_in);
1257                 if (tevent_req_nomem(subreq, req)) {
1258                         return tevent_req_post(req, ev);
1259                 }
1260                 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1261
1262                 return req;
1263         }
1264
1265         state->sec_status = NT_STATUS_OK;
1266
1267         subreq = tevent_queue_wait_send(state, state->ev,
1268                                         state->conn->calls.out_queue);
1269         if (tevent_req_nomem(subreq, req)) {
1270                 return tevent_req_post(req, ev);
1271         }
1272         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1273
1274         return req;
1275 }
1276
1277 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1278                                    enum tevent_req_state req_state)
1279 {
1280         struct dcerpc_do_bind_state *state =
1281                 tevent_req_data(req,
1282                 struct dcerpc_do_bind_state);
1283
1284         if (state->out_frag != NULL) {
1285                 state->out_frag->req = NULL;
1286                 state->out_frag = NULL;
1287         }
1288
1289         if (state->call != NULL) {
1290                 if (state->call == state->conn->calls.active) {
1291                         state->conn->calls.active = NULL;
1292                 }
1293                 ZERO_STRUCT(state->call->incoming);
1294                 DLIST_REMOVE(state->conn->calls.list, state->call);
1295                 state->call = NULL;
1296         }
1297 }
1298
1299 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1300 {
1301         struct tevent_req *req =
1302                 tevent_req_callback_data(subreq,
1303                 struct tevent_req);
1304         struct dcerpc_do_bind_state *state =
1305                 tevent_req_data(req,
1306                 struct dcerpc_do_bind_state);
1307         NTSTATUS status;
1308
1309         data_blob_free(&state->sec_out);
1310         status = gensec_update_recv(subreq, state, &state->sec_out);
1311         TALLOC_FREE(subreq);
1312         data_blob_free(&state->sec_in);
1313         state->sec_status = status;
1314         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1315                 status = NT_STATUS_OK;
1316         }
1317         if (!NT_STATUS_IS_OK(status)) {
1318                 tevent_req_nterror(req, status);
1319                 return;
1320         }
1321
1322         if (NT_STATUS_IS_OK(state->sec_status) &&
1323             state->sec_out.length == 0)
1324         {
1325                 tevent_req_done(req);
1326                 return;
1327         }
1328
1329         if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1330                 state->sec->client_hdr_signing =
1331                         gensec_have_feature(state->sec->gensec,
1332                                             GENSEC_FEATURE_SIGN_PKT_HEADER);
1333         }
1334
1335         subreq = tevent_queue_wait_send(state, state->ev,
1336                                         state->conn->calls.out_queue);
1337         if (tevent_req_nomem(subreq, req)) {
1338                 return;
1339         }
1340         tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1341 }
1342
1343 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1344 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1345 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1346
1347 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1348 {
1349         struct tevent_req *req =
1350                 tevent_req_callback_data(subreq,
1351                 struct tevent_req);
1352         struct dcerpc_do_bind_state *state =
1353                 tevent_req_data(req,
1354                 struct dcerpc_do_bind_state);
1355         struct dcerpc_do_bind_out_frag *frag;
1356         size_t auth_len = 0;
1357         NTSTATUS status;
1358         DATA_BLOB auth_info = data_blob_null;
1359         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1360         union dcerpc_payload u;
1361         uint32_t i;
1362         bool require_ack = false;
1363         bool use_trans = true;
1364         bool ok;
1365
1366         ok = tevent_queue_wait_recv(subreq);
1367         if (!ok) {
1368                 //status = NT_STATUS_INTERNAL_ERROR;
1369                 tevent_req_oom(req);
1370                 return;
1371         }
1372         TALLOC_FREE(subreq);
1373
1374         /*
1375          * the fragment belongs to the connection instead of the request
1376          * because it has to remain in case the request is canceled
1377          */
1378         frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1379         if (tevent_req_nomem(frag, req)) {
1380                 return;
1381         }
1382         frag->ev = state->ev;
1383         frag->conn = state->conn;
1384         frag->req = req;
1385         state->out_frag = frag;
1386
1387         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1388                 if (state->sec->client_hdr_signing &&
1389                     !state->proposed_hdr_signing)
1390                 {
1391                         state->proposed_hdr_signing = true;
1392                         pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1393                         require_ack = true;
1394                 }
1395         }
1396
1397         //TODO : DCERPC_PFC_FLAG_CONC_MPX
1398
1399         //TODO: remaining_pres
1400
1401         if (!state->conn->features.bind_done) {
1402                 frag->ptype = DCERPC_PKT_BIND;
1403         } else if (require_ack) {
1404                 frag->ptype = DCERPC_PKT_ALTER;
1405         } else if (state->remaining_pres > 0) {
1406                 frag->ptype = DCERPC_PKT_ALTER;
1407         } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1408                 frag->ptype = DCERPC_PKT_ALTER;
1409         } else {
1410                 frag->ptype = DCERPC_PKT_AUTH3;
1411         }
1412
1413         if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1414                 status = dcerpc_auth_blob(frag,
1415                                           state->sec->auth_type,
1416                                           state->sec->auth_level,
1417                                           0, /* auth_pad_length */
1418                                           state->sec->context_id, /* auth_context_id */
1419                                           &state->sec_out,
1420                                           &auth_info);
1421                 if (!NT_STATUS_IS_OK(status)) {
1422                         tevent_req_nterror(req, status);
1423                         return;
1424                 }
1425
1426                 auth_len = auth_info.length;
1427
1428                 if (auth_len) {
1429                         auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1430                 }
1431         }
1432
1433         state->num_ctx = state->num_pres;
1434         if (!state->conn->assoc->negotiate_done) {
1435                 state->num_ctx += 1;
1436         }
1437
1438         state->ctx_list = talloc_zero_array(frag,
1439                                             struct dcerpc_ctx_list,
1440                                             state->num_ctx);
1441         if (tevent_req_nomem(state->ctx_list, req)) {
1442                 return;
1443         }
1444
1445         for (i=0; i < state->num_pres; i++) {
1446                 state->ctx_list[i] = state->pres[i]->negotiate.req;
1447         }
1448
1449         if (!state->conn->assoc->negotiate_done) {
1450                 state->features = dcerpc_construct_bind_time_features(
1451                                         state->conn->assoc->client_features);
1452
1453                 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1454                 if (i > 0) {
1455                         state->ctx_list[i].abstract_syntax =
1456                                 state->ctx_list[i-1].abstract_syntax;
1457                 }
1458                 state->ctx_list[i].num_transfer_syntaxes = 1;
1459                 state->ctx_list[i].transfer_syntaxes = &state->features;
1460         }
1461
1462         switch (frag->ptype) {
1463         case DCERPC_PKT_BIND:
1464         case DCERPC_PKT_ALTER:
1465                 u.bind.max_xmit_frag    = state->conn->features.max_xmit_frag;
1466                 u.bind.max_recv_frag    = state->conn->features.max_recv_frag;
1467                 u.bind.assoc_group_id   = state->conn->assoc->assoc_group_id;
1468                 u.bind.num_contexts     = state->num_ctx;
1469                 u.bind.ctx_list         = state->ctx_list;
1470                 u.bind.auth_info        = auth_info;
1471                 break;
1472
1473         case DCERPC_PKT_AUTH3:
1474                 u.auth3._pad            = 0;
1475                 u.auth3.auth_info       = auth_info;
1476                 break;
1477         default:
1478                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1479                 return;
1480         }
1481
1482         status = dcerpc_ncacn_packet_blob(frag,
1483                                           frag->ptype,
1484                                           pfc_flags,
1485                                           auth_len,
1486                                           state->call->call_id,
1487                                           &u,
1488                                           &frag->blob);
1489         if (!NT_STATUS_IS_OK(status)) {
1490                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1491                 tevent_req_nterror(req, status);
1492                 return;
1493         }
1494
1495         if (frag->ptype == DCERPC_PKT_AUTH3) {
1496                 use_trans = false;
1497         }
1498
1499         if (frag->conn->transport.use_trans_fn == NULL) {
1500                 use_trans = false;
1501         }
1502
1503         if (frag->conn->loop.subreq != NULL) {
1504                 use_trans = false;
1505         }
1506
1507         if (frag->conn->features.concurrent_multiplex) {
1508                 use_trans = false;
1509         }
1510
1511         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1512                 use_trans = false;
1513         }
1514
1515         if (use_trans) {
1516                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1517                                                 frag->ev,
1518                                                 frag->conn->transport.write_queue);
1519                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1520                         return;
1521                 }
1522                 tevent_req_set_callback(frag->subreq_wait1,
1523                                         dcerpc_do_bind_out_frag_trans_wait1,
1524                                         frag);
1525                 /*
1526                  * we need to block reads until our write is
1527                  * the next in the write queue.
1528                  */
1529                 frag->conn->loop.subreq = frag->subreq_wait1;
1530                 frag->conn->loop.ev = frag->ev;
1531         }
1532
1533         /*
1534          * We need to add a dcerpc_write_fragment_queue_send/recv()
1535          */
1536
1537         frag->vector.iov_base = frag->blob.data;
1538         frag->vector.iov_len = frag->blob.length;
1539         subreq = tstream_writev_queue_send(frag, frag->ev,
1540                                            frag->conn->transport.stream,
1541                                            frag->conn->transport.write_queue,
1542                                            &frag->vector, 1);
1543         if (tevent_req_nomem(subreq, req)) {
1544                 return;
1545         }
1546         tevent_req_set_callback(subreq,
1547                                 dcerpc_do_bind_out_frag_done,
1548                                 frag);
1549
1550         if (use_trans) {
1551                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1552                                                 frag->ev,
1553                                                 frag->conn->transport.write_queue);
1554                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1555                         return;
1556                 }
1557                 tevent_req_set_callback(frag->subreq_wait2,
1558                                         dcerpc_do_bind_out_frag_trans_wait2,
1559                                         frag);
1560         }
1561
1562         if (frag->ptype == DCERPC_PKT_AUTH3) {
1563                 return;
1564         }
1565
1566         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1567         if (tevent_req_nterror(req, status)) {
1568                 return;
1569         }
1570 }
1571
1572 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1573 {
1574         struct dcerpc_do_bind_out_frag *frag =
1575                 tevent_req_callback_data(subreq,
1576                 struct dcerpc_do_bind_out_frag);
1577         struct dcerpc_connection *conn = frag->conn;
1578         NTSTATUS status;
1579         bool ok;
1580
1581         /*
1582          * always wait1???
1583          * TODO; what if the caller has been free'ed?
1584          * TALLOC_FREE(frag->subreq_write)
1585          */
1586
1587         frag->subreq_wait1 = NULL;
1588         conn->loop.subreq = NULL;
1589
1590         ok = tevent_queue_wait_recv(subreq);
1591         if (!ok) {
1592                 TALLOC_FREE(frag);
1593                 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1594                 return;
1595         }
1596
1597         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1598                 /*
1599                  * We added 3 entries into the queue,
1600                  * wait1, writev and wait2.
1601                  *
1602                  * There's more to write, we should not block
1603                  * further writev calls for a trans call.
1604                  *
1605                  * The wait2 stage will trigger the read.
1606                  */
1607                 TALLOC_FREE(subreq);
1608                 return;
1609         }
1610
1611         /*
1612          * we don't need wait2 anymore, we're sure that
1613          * we'll do a trans call.
1614          */
1615         TALLOC_FREE(frag->subreq_wait2);
1616
1617         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1618         if (!NT_STATUS_IS_OK(status)) {
1619                 TALLOC_FREE(frag);
1620                 dcerpc_connection_dead(conn, status);
1621                 return;
1622         }
1623
1624         /* we free subreq after tstream_cli_np_use_trans */
1625         TALLOC_FREE(subreq);
1626
1627         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1628         if (!NT_STATUS_IS_OK(status)) {
1629                 TALLOC_FREE(frag);
1630                 dcerpc_connection_dead(conn, status);
1631                 return;
1632         }
1633 }
1634
1635 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1636 {
1637         struct dcerpc_do_bind_out_frag *frag =
1638                 tevent_req_callback_data(subreq,
1639                 struct dcerpc_do_bind_out_frag);
1640         struct dcerpc_connection *conn = frag->conn;
1641         struct tevent_req *req = frag->req;
1642         NTSTATUS status;
1643         int ret;
1644         int sys_errno;
1645
1646         /*
1647          * If the caller has been free'ed, we have should
1648          * ignore any errors and just free 'frag'
1649          */
1650         if (req) {
1651                 struct dcerpc_do_bind_state *state =
1652                         tevent_req_data(req,
1653                         struct dcerpc_do_bind_state);
1654
1655                 state->out_frag = NULL;
1656         }
1657
1658         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1659         TALLOC_FREE(subreq);
1660         if (ret == -1) {
1661                 TALLOC_FREE(frag);
1662                 status = map_nt_error_from_unix_common(sys_errno);
1663                 dcerpc_connection_dead(conn, status);
1664                 return;
1665         }
1666
1667         if (frag->ptype == DCERPC_PKT_AUTH3) {
1668                 TALLOC_FREE(frag);
1669                 if (req == NULL) {
1670                         return;
1671                 }
1672                 tevent_req_done(req);
1673                 return;
1674         }
1675
1676         if (frag->subreq_wait2 != NULL) {
1677                 return;
1678         }
1679
1680         TALLOC_FREE(frag);
1681
1682         /* we need to wait for incoming pdus */
1683 }
1684
1685 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1686 {
1687         struct dcerpc_do_bind_out_frag *frag =
1688                 tevent_req_callback_data(subreq,
1689                 struct dcerpc_do_bind_out_frag);
1690         struct dcerpc_connection *conn = frag->conn;
1691         NTSTATUS status;
1692         bool ok;
1693
1694         frag->subreq_wait2 = NULL;
1695
1696         ok = tevent_queue_wait_recv(subreq);
1697         if (!ok) {
1698                 TALLOC_FREE(frag);
1699                 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1700                 return;
1701         }
1702
1703         TALLOC_FREE(subreq);
1704
1705         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1706         if (!NT_STATUS_IS_OK(status)) {
1707                 TALLOC_FREE(frag);
1708                 dcerpc_connection_dead(conn, status);
1709                 return;
1710         }
1711
1712         TALLOC_FREE(frag);
1713
1714         /* we need to wait for incoming pdus */
1715 }
1716
1717 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1718                                               struct ncacn_packet *pkt,
1719                                               DATA_BLOB frag)
1720 {
1721         struct dcerpc_do_bind_state *state =
1722                 tevent_req_data(req,
1723                 struct dcerpc_do_bind_state);
1724         NTSTATUS status;
1725         struct dcerpc_presentation *last_pres = NULL;
1726         size_t num_pres_ok = 0;
1727         size_t i;
1728
1729         /* Ensure we have the correct type. */
1730         switch (pkt->ptype) {
1731         case DCERPC_PKT_BIND_ACK:
1732         case DCERPC_PKT_ALTER_RESP:
1733                 if (!state->conn->features.bind_done) {
1734                         if (pkt->u.bind_ack.max_recv_frag < 1234) {
1735                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1736                         }
1737                         if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1738                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1739                         }
1740                         state->conn->features.max_recv_frag =
1741                                 pkt->u.bind_ack.max_recv_frag;
1742                         state->conn->features.max_xmit_frag =
1743                                 pkt->u.bind_ack.max_xmit_frag;
1744
1745                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1746                                 state->conn->features.concurrent_multiplex = true;
1747                         }
1748
1749                         state->conn->features.bind_done = true;
1750                 }
1751
1752                 if (!state->conn->assoc->negotiate_done) {
1753                         state->conn->assoc->negotiate_done = true;
1754                         state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1755                 }
1756
1757                 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1758                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1759                 }
1760
1761                 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1762                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1763                 }
1764
1765                 state->remaining_pres = 0;
1766
1767                 if (state->proposed_hdr_signing) {
1768                         if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1769                                 state->sec->hdr_signing = true;
1770                         }
1771                 }
1772
1773                 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1774                         struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1775
1776                         if (i < state->num_pres) {
1777                                 struct dcerpc_ack_ctx *pack =
1778                                         &state->pres[i]->negotiate.ack;
1779
1780                                 if (ack->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1781                                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1782                                 }
1783
1784                                 if (ack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1785                                         *pack = *ack;
1786                                         num_pres_ok += 1;
1787                                         continue;
1788                                 }
1789
1790                                 if (pack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1791                                         /*
1792                                          * if a presentation context was valid it must
1793                                          * be valid for the lifetime of the connection
1794                                          */
1795                                         return NT_STATUS_RPC_PROTOCOL_ERROR;
1796                                 }
1797
1798                                 *pack = *ack;
1799                                 last_pres = state->pres[i];
1800                                 continue;
1801                         }
1802
1803                         if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1804                                 continue;
1805                         }
1806
1807                         state->conn->assoc->features = state->conn->assoc->client_features;
1808                         state->conn->assoc->features &= ack->reason.negotiate;
1809                 }
1810
1811                 for (i = 0; i < state->num_pres; i++) {
1812                         struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1813                         bool ok;
1814
1815                         if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1816                                 continue;
1817                         }
1818
1819                         ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1820                                                  &ack->syntax);
1821                         if (!ok) {
1822                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1823                         }
1824                 }
1825
1826                 if (num_pres_ok == 0 && last_pres != NULL) {
1827                         status = dcerpc_presentation_status(last_pres);
1828                         tevent_req_nterror(req, status);
1829                         return NT_STATUS_OK;
1830                 }
1831
1832                 if (pkt->auth_length >= 8) {
1833                         struct tevent_req *subreq;
1834
1835                         state->sec_in = data_blob_talloc(state,
1836                                         pkt->u.bind_ack.auth_info.data + 8,
1837                                         pkt->u.bind_ack.auth_info.length - 8);
1838
1839                         subreq = gensec_update_send(state, state->ev,
1840                                                     state->sec->gensec,
1841                                                     state->sec_in);
1842                         if (tevent_req_nomem(subreq, req)) {
1843                                 return NT_STATUS_OK;
1844                         }
1845                         tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1846                         return NT_STATUS_OK;
1847                 }
1848
1849                 tevent_req_done(req);
1850                 return NT_STATUS_OK;
1851
1852         //case DCERPC_PKT_ALTER_RESP:
1853                 if (pkt->auth_length != 0) {
1854                         return NT_STATUS_NOT_IMPLEMENTED;
1855                 }
1856
1857                 return NT_STATUS_NOT_IMPLEMENTED;
1858 //TODO
1859 #if 0
1860                 /* Point the return values at the NDR data. */
1861                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1862
1863                 if (pkt->auth_length) {
1864                         /* We've already done integer wrap tests in
1865                          * dcerpc_check_auth(). */
1866                         payload.length = frag.length
1867                                          - DCERPC_RESPONSE_LENGTH
1868                                          - pad_len
1869                                          - DCERPC_AUTH_TRAILER_LENGTH
1870                                          - pkt->auth_length;
1871                 } else {
1872                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1873                 }
1874
1875                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1876                         if (pkt->drep[0] & DCERPC_DREP_LE) {
1877                                 state->response.bigendian = false;
1878                         } else {
1879                                 state->response.bigendian = true;
1880                         }
1881                 }
1882
1883                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1884                            (long unsigned int)frag.length,
1885                            (long unsigned int)payload.length,
1886                            (unsigned int)pad_len));
1887
1888                 /*
1889                  * If this is the first reply, and the allocation hint is
1890                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
1891                  * correct size.
1892                  */
1893
1894                 if ((state->response.blob.length == 0) &&
1895                     pkt->u.response.alloc_hint &&
1896                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
1897                         ok = data_blob_realloc(state, &state->response.blob,
1898                                                pkt->u.response.alloc_hint);
1899                         if (!ok) {
1900                                 DEBUG(0, ("reply alloc hint %d too "
1901                                           "large to allocate\n",
1902                                     (int)pkt->u.response.alloc_hint));
1903                                 return NT_STATUS_NO_MEMORY;
1904                         }
1905                 }
1906
1907                 new_total = state->response.ofs + payload.length;
1908
1909                 if (new_total > 15 * 1024 *1024) {
1910                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1911                 }
1912
1913                 missing = new_total - state->response.blob.length;
1914
1915                 if (missing > 0) {
1916                         ok = data_blob_realloc(state, &state->response.blob,
1917                                                new_total);
1918                         if (!ok) {
1919                                 DEBUG(0, ("reply alloc hint %d too "
1920                                           "large to allocate\n",
1921                                     (int)pkt->u.response.alloc_hint));
1922                                 return NT_STATUS_NO_MEMORY;
1923                         }
1924                 }
1925
1926                 memcpy(state->response.blob.data + state->response.ofs,
1927                        payload.data, payload.length);
1928                 state->response.ofs += payload.length;
1929
1930                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1931                         tevent_req_done(req);//TODO
1932                         return NT_STATUS_OK;
1933                 }
1934                 return NT_STATUS_OK;
1935 #endif
1936                 return NT_STATUS_NOT_IMPLEMENTED;
1937
1938         case DCERPC_PKT_FAULT:
1939
1940                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1941                           "code %s received from %s!\n",
1942                           dcerpc_errstr(talloc_tos(),
1943                           pkt->u.fault.status),
1944                           "TODO"));
1945
1946                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1947                 if (NT_STATUS_IS_OK(status)) {
1948                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
1949                 }
1950
1951                 tevent_req_nterror(req, status);//TODO
1952                 return NT_STATUS_OK;
1953         default:
1954                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1955                           (unsigned int)pkt->ptype,
1956                          "TODO"));
1957                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1958         }
1959
1960         return NT_STATUS_RPC_PROTOCOL_ERROR;
1961 }
1962
1963 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1964 {
1965         struct dcerpc_do_bind_state *state =
1966                 tevent_req_data(req,
1967                 struct dcerpc_do_bind_state);
1968         NTSTATUS status;
1969
1970         if (tevent_req_is_nterror(req, &status)) {
1971                 tevent_req_received(req);
1972                 return status;
1973         }
1974
1975         if (!NT_STATUS_IS_OK(state->sec_status)) {
1976                 status = state->sec_status;
1977                 tevent_req_received(req);
1978                 return status;
1979         }
1980
1981         tevent_req_received(req);
1982         return NT_STATUS_OK;
1983 }
1984
1985 struct dcerpc_do_request_out_frag;
1986
1987 struct dcerpc_do_request_state {
1988         struct tevent_context *ev;
1989         struct dcerpc_connection *conn;
1990         struct dcerpc_call *call;
1991         const struct GUID *object;
1992         uint16_t opnum;
1993         struct {
1994                 const DATA_BLOB *blob;
1995                 size_t ofs;
1996                 bool bigendian;
1997                 DATA_BLOB trailer;
1998                 size_t trailer_ofs;
1999         } request;
2000         bool verify_bitmask1;
2001         bool verify_pcontext;
2002         bool got_first;
2003         struct dcerpc_do_request_out_frag *out_frag;
2004         struct {
2005                 DATA_BLOB blob;
2006                 size_t ofs;
2007                 bool bigendian;
2008         } response;
2009 };
2010
2011 struct dcerpc_do_request_out_frag {
2012         struct tevent_context *ev;
2013         struct dcerpc_connection *conn;
2014         struct tevent_req *req;
2015         DATA_BLOB blob;
2016         bool is_last;
2017         struct iovec vector;
2018         struct tevent_req *subreq_wait1;
2019         struct tevent_req *subreq_wait2;
2020 };
2021
2022 static void dcerpc_do_request_cleanup(struct tevent_req *req,
2023                                       enum tevent_req_state req_state);
2024
2025 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
2026 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2027                                             void *private_data);
2028
2029 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2030                                                  struct ncacn_packet *pkt,
2031                                                  DATA_BLOB frag);
2032
2033 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
2034                                 struct tevent_context *ev,
2035                                 struct dcerpc_connection *conn,
2036                                 struct dcerpc_call *call,
2037                                 const struct GUID *object,
2038                                 uint16_t opnum,
2039                                 const DATA_BLOB *request,
2040                                 bool bigendian)
2041 {
2042         struct tevent_req *req;
2043         struct dcerpc_do_request_state *state;
2044         bool ok;
2045
2046         req = tevent_req_create(mem_ctx, &state,
2047                                 struct dcerpc_do_request_state);
2048         if (req == NULL) {
2049                 return NULL;
2050         }
2051         state->ev = ev;
2052         state->conn = conn;
2053         state->call = call;
2054         state->object = object;
2055         state->opnum = opnum;
2056         state->request.blob = request;
2057         state->request.bigendian = bigendian;
2058
2059         dcerpc_do_request_verification_trailer(req);
2060         if (!tevent_req_is_in_progress(req)) {
2061                 return tevent_req_post(req, ev);
2062         }
2063
2064         state->call->incoming.req = req;
2065         state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
2066         DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
2067         tevent_req_defer_callback(req, ev);
2068         tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
2069
2070         ok = tevent_queue_add(state->conn->calls.out_queue,
2071                               state->ev,
2072                               req,
2073                               dcerpc_do_request_out_frag_next,
2074                               NULL);
2075         if (!ok) {
2076                 tevent_req_nomem(NULL, req);
2077                 return tevent_req_post(req, ev);
2078         }
2079
2080         return req;
2081 }
2082
2083 static void dcerpc_do_request_cleanup(struct tevent_req *req,
2084                                       enum tevent_req_state req_state)
2085 {
2086         struct dcerpc_do_request_state *state =
2087                 tevent_req_data(req,
2088                 struct dcerpc_do_request_state);
2089
2090         if (state->out_frag != NULL) {
2091                 state->out_frag->req = NULL;
2092                 state->out_frag = NULL;
2093         }
2094
2095         if (state->call != NULL) {
2096                 if (state->call == state->conn->calls.active) {
2097                         state->conn->calls.active = NULL;
2098                 }
2099                 ZERO_STRUCT(state->call->incoming);
2100                 DLIST_REMOVE(state->conn->calls.list, state->call);
2101                 state->call = NULL;
2102         }
2103 }
2104
2105 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
2106 {
2107         struct dcerpc_do_request_state *state =
2108                 tevent_req_data(req,
2109                 struct dcerpc_do_request_state);
2110         struct dcerpc_sec_verification_trailer *t;
2111         struct dcerpc_sec_vt *c = NULL;
2112         struct ndr_push *ndr = NULL;
2113         enum ndr_err_code ndr_err;
2114         size_t align = 0;
2115         size_t pad = 0;
2116
2117         if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
2118                 return;
2119         }
2120
2121         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
2122         if (tevent_req_nomem(t, req)) {
2123                 return;
2124         }
2125
2126         if (!state->call->sec->verified_bitmask1) {
2127                 t->commands = talloc_realloc(t, t->commands,
2128                                              struct dcerpc_sec_vt,
2129                                              t->count.count + 1);
2130                 if (tevent_req_nomem(t->commands, req)) {
2131                         return;
2132                 }
2133                 c = &t->commands[t->count.count++];
2134                 ZERO_STRUCTP(c);
2135
2136                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
2137                 if (state->call->sec->client_hdr_signing) {
2138                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
2139                 }
2140                 state->verify_bitmask1 = true;
2141         }
2142
2143         if (!state->call->pres->verified_pcontext) {
2144                 t->commands = talloc_realloc(t, t->commands,
2145                                              struct dcerpc_sec_vt,
2146                                              t->count.count + 1);
2147                 if (tevent_req_nomem(t->commands, req)) {
2148                         return;
2149                 }
2150                 c = &t->commands[t->count.count++];
2151                 ZERO_STRUCTP(c);
2152
2153                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
2154                 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
2155                 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
2156
2157                 state->verify_pcontext = true;
2158         }
2159
2160         if (!state->call->sec->hdr_signing) {
2161                 t->commands = talloc_realloc(t, t->commands,
2162                                              struct dcerpc_sec_vt,
2163                                              t->count.count + 1);
2164                 if (tevent_req_nomem(t->commands, req)) {
2165                         return;
2166                 }
2167                 c = &t->commands[t->count.count++];
2168                 ZERO_STRUCTP(c);
2169
2170                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
2171                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
2172                 if (state->request.bigendian) {
2173                         c->u.header2.drep[0] = 0;
2174                 } else {
2175                         c->u.header2.drep[0] = DCERPC_DREP_LE;
2176                 }
2177                 c->u.header2.drep[1] = 0;
2178                 c->u.header2.drep[2] = 0;
2179                 c->u.header2.drep[3] = 0;
2180                 c->u.header2.call_id = state->call->call_id;
2181                 c->u.header2.context_id = 0;
2182                 c->u.header2.opnum = state->opnum;
2183         }
2184
2185         if (t->count.count == 0) {
2186                 TALLOC_FREE(t);
2187                 return;
2188         }
2189
2190         c = &t->commands[t->count.count - 1];
2191         c->command |= DCERPC_SEC_VT_COMMAND_END;
2192
2193         if (DEBUGLEVEL >= 10) {
2194                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
2195         }
2196
2197         ndr = ndr_push_init_ctx(state);
2198         if (tevent_req_nomem(ndr, req)) {
2199                 return;
2200         }
2201
2202         //TODO if (state->request.bigendian)
2203
2204         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
2205                                                 NDR_SCALARS | NDR_BUFFERS,
2206                                                 t);
2207         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2208                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2209                 tevent_req_nterror(req, status);
2210                 return;
2211         }
2212         state->request.trailer = ndr_push_blob(ndr);
2213
2214         align = state->request.blob->length & 0x3;
2215         if (align > 0) {
2216                 pad = 4 - align;
2217         }
2218         if (pad > 0) {
2219                 bool ok;
2220                 uint8_t *p;
2221                 const uint8_t zeros[4] = { 0, };
2222
2223                 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
2224                 if (!ok) {
2225                         tevent_req_oom(req);
2226                         return;
2227                 }
2228
2229                 /* move the padding to the start */
2230                 p = state->request.trailer.data;
2231                 memmove(p + pad, p, state->request.trailer.length - pad);
2232                 memset(p, 0, pad);
2233         }
2234
2235         return;
2236 }
2237
2238 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
2239 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
2240 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
2241
2242 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2243                                             void *private_data)
2244 {
2245         struct dcerpc_do_request_state *state =
2246                 tevent_req_data(req,
2247                 struct dcerpc_do_request_state);
2248         struct dcerpc_do_request_out_frag *frag;
2249         size_t hdr_len = DCERPC_REQUEST_LENGTH;
2250         size_t auth_len;
2251         size_t frag_len;
2252         uint8_t flags = 0;
2253         size_t pad_len;
2254         size_t data_left;
2255         size_t data_thistime;
2256         size_t trailer_left;
2257         size_t trailer_thistime = 0;
2258         size_t total_left;
2259         size_t total_thistime;
2260         NTSTATUS status;
2261         union dcerpc_payload u;
2262         bool ok;
2263         struct tevent_req *subreq;
2264         bool use_trans = true;
2265
2266         if (state->object) {
2267                 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
2268                 hdr_len += 16;
2269         }
2270
2271         /*
2272          * the fragment belongs to the connection instead of the request
2273          * because it has to remain in case the request is canceled
2274          */
2275         frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2276         if (tevent_req_nomem(frag, req)) {
2277                 return;
2278         }
2279         frag->ev = state->ev;
2280         frag->conn = state->conn;
2281         frag->req = req;
2282         state->out_frag = frag;
2283
2284         data_left = state->request.blob->length - state->request.ofs;
2285         trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2286         total_left = data_left + trailer_left;
2287         if (total_left < data_left || total_left < trailer_left) {
2288                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2289                 return;
2290         }
2291
2292         status = dcerpc_guess_pdu_sizes(state->call->sec,
2293                                     hdr_len, total_left,
2294                                     state->conn->features.max_xmit_frag,
2295                                     DCERPC_PAYLOAD_PADDING_SIZE,
2296                                     &total_thistime,
2297                                     &frag_len, &auth_len, &pad_len);
2298         if (!NT_STATUS_IS_OK(status)) {
2299                 tevent_req_nterror(req, status);
2300                 return;
2301         }
2302
2303         if (state->request.ofs == 0) {
2304                 flags |= DCERPC_PFC_FLAG_FIRST;
2305         }
2306
2307         if (total_thistime == total_left) {
2308                 flags |= DCERPC_PFC_FLAG_LAST;
2309         }
2310
2311         data_thistime = MIN(total_thistime, data_left);
2312         if (data_thistime < total_thistime) {
2313                 trailer_thistime = total_thistime - data_thistime;
2314         }
2315
2316         ZERO_STRUCT(u.request);
2317
2318         u.request.alloc_hint    = total_left;
2319         u.request.context_id    = state->call->pres->context_id;
2320         u.request.opnum         = state->opnum;
2321         if (state->object) {
2322                 u.request.object.object = *state->object;
2323         }
2324 //TODO pass state->request.bigendian
2325         status = dcerpc_ncacn_packet_blob(frag,
2326                                           DCERPC_PKT_REQUEST,
2327                                           flags,
2328                                           auth_len,
2329                                           state->call->call_id,
2330                                           &u,
2331                                           &frag->blob);
2332         if (!NT_STATUS_IS_OK(status)) {
2333                 tevent_req_nterror(req, status);
2334                 return;
2335         }
2336
2337         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2338          * compute it right for requests because the auth trailer is missing
2339          * at this stage */
2340         dcerpc_set_frag_length(&frag->blob, frag_len);
2341
2342         if (data_thistime > 0) {
2343                 const uint8_t *data_ptr;
2344
2345                 data_ptr = state->request.blob->data;
2346                 data_ptr += state->request.ofs;
2347
2348                 /* Copy in the data. */
2349                 ok = data_blob_append(frag, &frag->blob,
2350                                       data_ptr, data_thistime);
2351                 if (!ok) {
2352                         tevent_req_oom(req);
2353                         return;
2354                 }
2355
2356                 state->request.ofs += data_thistime;
2357         }
2358
2359         if (trailer_thistime > 0) {
2360                 const uint8_t *trailer_ptr;
2361
2362                 trailer_ptr = state->request.trailer.data;
2363                 trailer_ptr += state->request.trailer_ofs;
2364
2365                 /* Copy in the data. */
2366                 ok = data_blob_append(frag, &frag->blob,
2367                                       trailer_ptr, trailer_thistime);
2368                 if (!ok) {
2369                         tevent_req_oom(req);
2370                         return;
2371                 }
2372
2373                 state->request.trailer_ofs += trailer_thistime;
2374         }
2375
2376         switch (state->call->sec->auth_level) {
2377         case DCERPC_AUTH_LEVEL_NONE:
2378         case DCERPC_AUTH_LEVEL_CONNECT:
2379         case DCERPC_AUTH_LEVEL_PACKET:
2380                 break;
2381         case DCERPC_AUTH_LEVEL_INTEGRITY:
2382         case DCERPC_AUTH_LEVEL_PRIVACY:
2383                 status = dcerpc_response_auth_blob(state->call->sec,
2384                                                 pad_len,
2385                                                 auth_len,
2386                                                 &frag->blob);
2387                 if (!NT_STATUS_IS_OK(status)) {
2388                         tevent_req_nterror(req, status);
2389                         return;
2390                 }
2391                 break;
2392         default:
2393                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2394                 return;
2395         }
2396
2397         frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2398
2399         if (!frag->is_last) {
2400                 use_trans = false;
2401         }
2402
2403         if (frag->conn->transport.use_trans_fn == NULL) {
2404                 use_trans = false;
2405         }
2406
2407         if (frag->conn->loop.subreq != NULL) {
2408                 use_trans = false;
2409         }
2410
2411         if (frag->conn->features.concurrent_multiplex) {
2412                 use_trans = false;
2413         }
2414
2415         if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2416                 use_trans = false;
2417         }
2418
2419         if (use_trans) {
2420                 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2421                                                 frag->ev,
2422                                                 frag->conn->transport.write_queue);
2423                 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2424                         return;
2425                 }
2426                 tevent_req_set_callback(frag->subreq_wait1,
2427                                         dcerpc_do_request_out_frag_trans_wait1,
2428                                         frag);
2429                 /*
2430                  * we need to block reads until our write is
2431                  * the next in the write queue.
2432                  */
2433                 frag->conn->loop.subreq = frag->subreq_wait1;
2434                 frag->conn->loop.ev = frag->ev;
2435         }
2436
2437         /*
2438          * We need to add a dcerpc_write_fragment_queue_send/recv()
2439          */
2440
2441         frag->vector.iov_base = frag->blob.data;
2442         frag->vector.iov_len = frag->blob.length;
2443         subreq = tstream_writev_queue_send(frag, frag->ev,
2444                                            frag->conn->transport.stream,
2445                                            frag->conn->transport.write_queue,
2446                                            &frag->vector, 1);
2447         if (tevent_req_nomem(subreq, req)) {
2448                 return;
2449         }
2450         tevent_req_set_callback(subreq,
2451                                 dcerpc_do_request_out_frag_done,
2452                                 frag);
2453
2454         if (use_trans) {
2455                 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2456                                                 frag->ev,
2457                                                 frag->conn->transport.write_queue);
2458                 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2459                         return;
2460                 }
2461                 tevent_req_set_callback(frag->subreq_wait2,
2462                                         dcerpc_do_request_out_frag_trans_wait2,
2463                                         frag);
2464         }
2465
2466         if (!frag->is_last) {
2467                 return;
2468         }
2469
2470         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2471         if (tevent_req_nterror(req, status)) {
2472                 return;
2473         }
2474 }
2475
2476 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2477 {
2478         struct dcerpc_do_request_out_frag *frag =
2479                 tevent_req_callback_data(subreq,
2480                 struct dcerpc_do_request_out_frag);
2481         struct tevent_req *req = frag->req;
2482         NTSTATUS status;
2483         bool ok;
2484
2485         /*
2486          * TODO; what if the caller has been free'ed?
2487          */
2488
2489         frag->subreq_wait1 = NULL;
2490         frag->conn->loop.subreq = NULL;
2491
2492         ok = tevent_queue_wait_recv(subreq);
2493         if (!ok) {
2494                 status = NT_STATUS_INTERNAL_ERROR;
2495                 TALLOC_FREE(frag);
2496                 if (req) {
2497                         tevent_req_nterror(req, status);
2498                 }
2499                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2500                 return;
2501         }
2502
2503         if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2504                 /*
2505                  * We added 3 entries into the queue,
2506                  * wait1, writev and wait2.
2507                  *
2508                  * There's more to write, we should not block
2509                  * further writev calls for a trans call.
2510                  *
2511                  * The wait2 stage will trigger the read.
2512                  */
2513                 TALLOC_FREE(subreq);
2514                 return;
2515         }
2516
2517         /*
2518          * we don't need wait2 anymore, we're sure that
2519          * we'll do a trans call.
2520          */
2521         TALLOC_FREE(frag->subreq_wait2);
2522
2523         status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2524         if (!NT_STATUS_IS_OK(status)) {
2525                 TALLOC_FREE(frag);
2526                 if (req) {
2527                         tevent_req_nterror(req, status);
2528                 }
2529                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2530                 return;
2531         }
2532
2533         /* we free subreq after tstream_cli_np_use_trans */
2534         TALLOC_FREE(subreq);
2535
2536         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2537         if (!NT_STATUS_IS_OK(status)) {
2538                 TALLOC_FREE(frag);
2539                 if (req) {
2540                         tevent_req_nterror(req, status);
2541                 }
2542                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2543                 return;
2544         }
2545 }
2546
2547 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2548 {
2549         struct dcerpc_do_request_out_frag *frag =
2550                 tevent_req_callback_data(subreq,
2551                 struct dcerpc_do_request_out_frag);
2552         struct tevent_req *req = frag->req;
2553         NTSTATUS status;
2554         int ret;
2555         int sys_errno;
2556
2557         /*
2558          * If the caller has been free'ed, we have should
2559          * ignore any errors and just free 'frag'
2560          */
2561         if (req) {
2562                 struct dcerpc_do_request_state *state =
2563                         tevent_req_data(req,
2564                         struct dcerpc_do_request_state);
2565
2566                 state->out_frag = NULL;
2567         }
2568
2569         ret = tstream_writev_queue_recv(subreq, &sys_errno);
2570         TALLOC_FREE(subreq);
2571         if (ret == -1) {
2572                 TALLOC_FREE(frag);
2573                 status = map_nt_error_from_unix_common(sys_errno);
2574                 if (req) {
2575                         tevent_req_nterror(req, status);
2576                 }
2577                 return;
2578         }
2579
2580         if (frag->subreq_wait2 != NULL) {
2581                 return;
2582         }
2583
2584         if (frag->is_last) {
2585                 TALLOC_FREE(frag);
2586                 return;
2587         }
2588         TALLOC_FREE(frag);
2589
2590         if (req == NULL) {
2591                 return;
2592         }
2593
2594         dcerpc_do_request_out_frag_next(req, NULL);
2595 }
2596
2597 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2598 {
2599         struct dcerpc_do_request_out_frag *frag =
2600                 tevent_req_callback_data(subreq,
2601                 struct dcerpc_do_request_out_frag);
2602         struct tevent_req *req = frag->req;
2603         NTSTATUS status;
2604         bool ok;
2605
2606         frag->subreq_wait2 = NULL;
2607
2608         ok = tevent_queue_wait_recv(subreq);
2609         if (!ok) {
2610                 status = NT_STATUS_INTERNAL_ERROR;
2611                 TALLOC_FREE(frag);
2612                 if (req) {
2613                         tevent_req_nterror(req, status);
2614                 }
2615                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2616                 return;
2617         }
2618
2619         TALLOC_FREE(subreq);
2620
2621         status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2622         if (!NT_STATUS_IS_OK(status)) {
2623                 TALLOC_FREE(frag);
2624                 if (req) {
2625                         tevent_req_nterror(req, status);
2626                 }
2627                 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2628                 return;
2629         }
2630
2631         TALLOC_FREE(frag);
2632
2633         /* we need to wait for incoming pdus */
2634 }
2635
2636 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2637                                                  struct ncacn_packet *pkt,
2638                                                  DATA_BLOB frag)
2639 {
2640         struct dcerpc_do_request_state *state =
2641                 tevent_req_data(req,
2642                 struct dcerpc_do_request_state);
2643         NTSTATUS error;
2644         NTSTATUS status;
2645         size_t pad_len = 0;
2646         DATA_BLOB payload;
2647         size_t new_total;
2648         size_t missing;
2649         bool ok;
2650
2651         /* Ensure we have the correct type. */
2652         switch (pkt->ptype) {
2653         case DCERPC_PKT_RESPONSE:
2654
2655                 /* Here's where we deal with incoming sign/seal. */
2656                 error = dcerpc_check_pdu_auth(state->call->sec,
2657                                         pkt,
2658                                         &pkt->u.response.stub_and_verifier,
2659                                         DCERPC_RESPONSE_LENGTH,
2660                                         &frag, &pad_len);
2661                 if (!NT_STATUS_IS_OK(error)) {
2662                         return error;
2663                 }
2664
2665                 if (!state->got_first) {
2666                         state->got_first = true;
2667
2668                         if (pkt->drep[0] & DCERPC_DREP_LE) {
2669                                 state->response.bigendian = false;
2670                         } else {
2671                                 state->response.bigendian = true;
2672                         }
2673
2674                         if (state->verify_bitmask1) {
2675                                 state->call->sec->verified_bitmask1 = true;
2676                         }
2677
2678                         if (state->verify_pcontext) {
2679                                 state->call->pres->verified_pcontext = true;
2680                         }
2681                 }
2682
2683                 if (state->response.bigendian) {
2684                         if (pkt->drep[0] != 0) {
2685                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2686                         }
2687                 } else {
2688                         if (pkt->drep[0] != DCERPC_DREP_LE) {
2689                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2690                         }
2691                 }
2692                 if (pkt->drep[1] != 0) {
2693                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2694                 }
2695                 if (pkt->drep[2] != 0) {
2696                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2697                 }
2698                 if (pkt->drep[3] != 0) {
2699                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2700                 }
2701
2702                 if (pkt->u.response.context_id != state->call->pres->context_id) {
2703                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2704                 }
2705
2706                 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2707                         return NT_STATUS_RPC_PROTOCOL_ERROR;
2708                 }
2709 //TODO
2710                 /* Point the return values at the NDR data. */
2711                 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2712
2713                 if (pkt->auth_length) {
2714                         /* We've already done integer wrap tests in
2715                          * dcerpc_check_auth(). */
2716                         payload.length = frag.length
2717                                          - DCERPC_RESPONSE_LENGTH
2718                                          - pad_len
2719                                          - DCERPC_AUTH_TRAILER_LENGTH
2720                                          - pkt->auth_length;
2721                 } else {
2722                         payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2723                 }
2724
2725                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2726                            (long unsigned int)frag.length,
2727                            (long unsigned int)payload.length,
2728                            (unsigned int)pad_len));
2729
2730                 /*
2731                  * If this is the first reply, and the allocation hint is
2732                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
2733                  * correct size.
2734                  */
2735
2736                 if ((state->response.blob.length == 0) &&
2737                     pkt->u.response.alloc_hint &&
2738                     (pkt->u.response.alloc_hint < 15*1024*1024)) {
2739                         ok = data_blob_realloc(state, &state->response.blob,
2740                                                pkt->u.response.alloc_hint);
2741                         if (!ok) {
2742                                 DEBUG(0, ("reply alloc hint %d too "
2743                                           "large to allocate\n",
2744                                     (int)pkt->u.response.alloc_hint));
2745                                 return NT_STATUS_NO_MEMORY;
2746                         }
2747                 }
2748
2749                 new_total = state->response.ofs + payload.length;
2750
2751                 if (new_total > 15 * 1024 *1024) {
2752                         return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2753                 }
2754
2755                 missing = new_total - state->response.blob.length;
2756
2757                 if (missing > 0) {
2758                         ok = data_blob_realloc(state, &state->response.blob,
2759                                                new_total);
2760                         if (!ok) {
2761                                 DEBUG(0, ("reply alloc hint %d too "
2762                                           "large to allocate\n",
2763                                     (int)pkt->u.response.alloc_hint));
2764                                 return NT_STATUS_NO_MEMORY;
2765                         }
2766                 }
2767
2768                 memcpy(state->response.blob.data + state->response.ofs,
2769                        payload.data, payload.length);
2770                 state->response.ofs += payload.length;
2771
2772                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2773                         tevent_req_done(req);//TODO
2774                         return NT_STATUS_OK;
2775                 }
2776
2777                 return dcerpc_connection_loop_restart(state->conn, state->ev);
2778
2779         case DCERPC_PKT_FAULT:
2780
2781                 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2782                           "code %s received from %s!\n",
2783                           dcerpc_errstr(talloc_tos(),
2784                           pkt->u.fault.status),
2785                           "TODO"));
2786
2787                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2788                 if (NT_STATUS_IS_OK(status)) {
2789                         status = NT_STATUS_RPC_PROTOCOL_ERROR;
2790                 }
2791
2792                 tevent_req_nterror(req, status);//TODO
2793                 return NT_STATUS_OK;
2794         default:
2795                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2796                           (unsigned int)pkt->ptype,
2797                          "TODO"));
2798                 return NT_STATUS_RPC_PROTOCOL_ERROR;
2799         }
2800 }
2801
2802 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2803                                 TALLOC_CTX *mem_ctx,
2804                                 DATA_BLOB *response,
2805                                 bool *bigendian)
2806 {
2807         struct dcerpc_do_request_state *state =
2808                 tevent_req_data(req,
2809                 struct dcerpc_do_request_state);
2810         NTSTATUS status;
2811
2812         if (tevent_req_is_nterror(req, &status)) {
2813                 tevent_req_received(req);
2814                 return status;
2815         }
2816
2817         /* return data to caller and assign it ownership of memory */
2818         response->data = talloc_move(mem_ctx, &state->response.blob.data);
2819         response->length = state->response.blob.length;
2820         *bigendian = state->response.bigendian;
2821
2822         tevent_req_received(req);
2823         return NT_STATUS_OK;
2824 }
2825
2826 struct dcerpc_submit_fault_frag {
2827         DATA_BLOB blob;
2828         struct iovec vector;
2829 };
2830
2831 static void dcerpc_submit_fault_done(struct tevent_req *subreq);
2832
2833 static NTSTATUS dcerpc_submit_fault(struct dcerpc_connection *conn,
2834                                     struct tevent_context *ev,
2835                                     uint32_t call_id,
2836                                     uint32_t context_id,
2837                                     NTSTATUS nt_status)
2838 {
2839         struct dcerpc_submit_fault_frag *frag;
2840         NTSTATUS error;
2841         union dcerpc_payload u;
2842         struct tevent_req *subreq;
2843
2844         if (!dcerpc_connection_is_connected(conn)) {
2845                 return NT_STATUS_OK;
2846         }
2847
2848         /*
2849          * the fragment belongs to the connection instead of the request
2850          * because it has to remain in case the request is canceled
2851          */
2852         frag = talloc_zero(conn, struct dcerpc_submit_fault_frag);
2853         if (frag == NULL) {
2854                 return NT_STATUS_NO_MEMORY;
2855         }
2856
2857         ZERO_STRUCT(u.fault);
2858         u.fault.context_id = context_id;
2859         u.fault.status = dcerpc_fault_from_nt_status(nt_status);
2860
2861         error = dcerpc_ncacn_packet_blob(frag,
2862                                          DCERPC_PKT_FAULT,
2863                                          DCERPC_PFC_FLAG_FIRST |
2864                                          DCERPC_PFC_FLAG_LAST,
2865                                          0,
2866                                          call_id,
2867                                          &u,
2868                                          &frag->blob);
2869         if (!NT_STATUS_IS_OK(error)) {
2870                 TALLOC_FREE(frag);
2871                 return error;
2872         }
2873
2874         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2875          * compute it right for requests because the auth trailer is missing
2876          * at this stage */
2877         //dcerpc_set_frag_length(&frag->blob, frag_len);
2878
2879         /*
2880          * We need to add a dcerpc_write_fragment_queue_send/recv()
2881          */
2882
2883         frag->vector.iov_base = frag->blob.data;
2884         frag->vector.iov_len = frag->blob.length;
2885         subreq = tstream_writev_queue_send(frag, ev,
2886                                            conn->transport.stream,
2887                                            conn->transport.write_queue,
2888                                            &frag->vector, 1);
2889         if (subreq == NULL) {
2890                 TALLOC_FREE(frag);
2891                 return NT_STATUS_NO_MEMORY;
2892         }
2893         tevent_req_set_callback(subreq,
2894                                 dcerpc_submit_fault_done,
2895                                 frag);
2896
2897         return NT_STATUS_OK;
2898 }
2899
2900 static void dcerpc_submit_fault_done(struct tevent_req *subreq)
2901 {
2902         struct dcerpc_submit_fault_frag *frag =
2903                 tevent_req_callback_data(subreq,
2904                 struct dcerpc_submit_fault_frag);
2905
2906         TALLOC_FREE(subreq);
2907
2908         TALLOC_FREE(frag);
2909 }
2910
2911 struct dcerpc_submit_shutdown_frag {
2912         struct dcerpc_connection *conn;
2913         DATA_BLOB blob;
2914         struct iovec vector;
2915 };
2916
2917 static void dcerpc_submit_shutdown_done(struct tevent_req *subreq);
2918
2919 static NTSTATUS dcerpc_submit_shutdown(struct dcerpc_connection *conn,
2920                                        struct tevent_context *ev)
2921 {
2922         struct dcerpc_submit_shutdown_frag *frag;
2923         NTSTATUS error;
2924         union dcerpc_payload u;
2925         struct tevent_req *subreq;
2926
2927         if (!dcerpc_connection_is_connected(conn)) {
2928                 return NT_STATUS_OK;
2929         }
2930
2931         TALLOC_FREE(conn->loop.subreq);
2932
2933         /*
2934          * the fragment belongs to the connection instead of the request
2935          * because it has to remain in case the request is canceled
2936          */
2937         frag = talloc_zero(conn, struct dcerpc_submit_shutdown_frag);
2938         if (frag == NULL) {
2939                 return NT_STATUS_NO_MEMORY;
2940         }
2941         frag->conn = conn;
2942
2943         ZERO_STRUCT(u.shutdown);
2944
2945         error = dcerpc_ncacn_packet_blob(frag,
2946                                          DCERPC_PKT_SHUTDOWN,
2947                                          DCERPC_PFC_FLAG_FIRST |
2948                                          DCERPC_PFC_FLAG_LAST,
2949                                          0, /* auth_length */
2950                                          0, /* call_id */
2951                                          &u,
2952                                          &frag->blob);
2953         if (!NT_STATUS_IS_OK(error)) {
2954                 TALLOC_FREE(frag);
2955                 return error;
2956         }
2957
2958         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2959          * compute it right for requests because the auth trailer is missing
2960          * at this stage */
2961         //dcerpc_set_frag_length(&frag->blob, frag_len);
2962
2963         /*
2964          * We need to add a dcerpc_write_fragment_queue_send/recv()
2965          */
2966
2967         frag->vector.iov_base = frag->blob.data;
2968         frag->vector.iov_len = frag->blob.length;
2969         subreq = tstream_writev_queue_send(frag, ev,
2970                                            conn->transport.stream,
2971                                            conn->transport.write_queue,
2972                                            &frag->vector, 1);
2973         if (subreq == NULL) {
2974                 TALLOC_FREE(frag);
2975                 return NT_STATUS_NO_MEMORY;
2976         }
2977         tevent_req_set_callback(subreq,
2978                                 dcerpc_submit_shutdown_done,
2979                                 frag);
2980
2981         conn->loop.subreq = subreq;
2982
2983         return NT_STATUS_OK;
2984 }
2985
2986 static void dcerpc_submit_shutdown_done(struct tevent_req *subreq)
2987 {
2988         struct dcerpc_submit_shutdown_frag *frag =
2989                 tevent_req_callback_data(subreq,
2990                 struct dcerpc_submit_shutdown_frag);
2991         struct dcerpc_connection *conn = frag->conn;
2992
2993         TALLOC_FREE(subreq);
2994
2995         TALLOC_FREE(frag);
2996
2997         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
2998 }
2999
3000 struct dcerpc_server_connection_loop_state {
3001         struct tevent_context *ev;
3002         struct dcerpc_connection *conn;
3003
3004         struct dcerpc_server *server;
3005
3006         struct dcerpc_server_association *assoc;
3007
3008         uint32_t last_call_id;
3009
3010         bool allow_incoming;
3011
3012         size_t num_secs;
3013         struct db_context *secs;
3014
3015         size_t num_pres;
3016         struct db_context *pres;
3017 };
3018
3019 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
3020                                       enum tevent_req_state req_state);
3021
3022 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
3023                                                              struct ncacn_packet *pkt,
3024                                                              DATA_BLOB frag);
3025
3026 struct tevent_req *dcerpc_server_connection_loop_send(TALLOC_CTX *mem_ctx,
3027                                 struct tevent_context *ev,
3028                                 struct dcerpc_connection *conn,
3029                                 struct dcerpc_server *server)
3030 {
3031         struct tevent_req *req;
3032         struct dcerpc_server_connection_loop_state *state;
3033         struct dcerpc_call *call;
3034
3035         req = tevent_req_create(mem_ctx, &state,
3036                                 struct dcerpc_server_connection_loop_state);
3037         if (req == NULL) {
3038                 return NULL;
3039         }
3040         state->ev = ev;
3041         state->conn = conn;
3042
3043         if (state->conn->calls.new_call != NULL) {
3044                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3045                 return tevent_req_post(req, ev);
3046         }
3047
3048         call = talloc_zero(state, struct dcerpc_call);
3049         if (call == NULL) {
3050                 return NULL;
3051         }
3052
3053         call->incoming.req = req;
3054         call->incoming.handler = dcerpc_server_connection_loop_handle_in_frag;
3055         conn->calls.new_call = call;
3056         tevent_req_defer_callback(req, ev);
3057         tevent_req_set_cleanup_fn(req, dcerpc_server_connection_loop_cleanup);
3058
3059         state->allow_incoming = true;
3060         //TODO different dcerpc_connection_dead() behavior as server?
3061
3062         return req;
3063 }
3064
3065 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
3066                                                   enum tevent_req_state req_state)
3067 {
3068         struct dcerpc_server_connection_loop_state *state =
3069                 tevent_req_data(req,
3070                 struct dcerpc_server_connection_loop_state);
3071
3072         state->allow_incoming = false;
3073
3074         if (state->conn != NULL) {
3075                 TALLOC_FREE(state->conn->calls.new_call);
3076                 state->conn = NULL;
3077         }
3078 }
3079
3080 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
3081                                                              struct ncacn_packet *pkt,
3082                                                              DATA_BLOB frag)
3083 {
3084         struct dcerpc_server_connection_loop_state *state =
3085                 tevent_req_data(req,
3086                 struct dcerpc_server_connection_loop_state);
3087
3088         if (!state->allow_incoming) {
3089                 DEBUG(0, ("Unexpected packet type %u received from %s!\n",
3090                           (unsigned int)pkt->ptype,
3091                          "TODO"));
3092                 return NT_STATUS_RPC_PROTOCOL_ERROR;
3093         }
3094
3095         /* Ensure we have the correct type. */
3096         switch (pkt->ptype) {
3097         case DCERPC_PKT_BIND:
3098                 if (state->conn->features.bind_done) {
3099                         return NT_STATUS_RPC_PROTOCOL_ERROR;
3100                 }
3101                 state->allow_incoming = false;
3102                 break;
3103
3104         case DCERPC_PKT_AUTH3:
3105                 if (!state->conn->features.bind_done) {
3106                         return NT_STATUS_RPC_PROTOCOL_ERROR;
3107                 }
3108                 break;
3109
3110         case DCERPC_PKT_ALTER:
3111                 if (!state->conn->features.bind_done) {
3112                         return NT_STATUS_RPC_PROTOCOL_ERROR;
3113                 }
3114                 break;
3115
3116         case DCERPC_PKT_REQUEST:
3117                 if (!state->conn->features.bind_done) {
3118                         return NT_STATUS_RPC_PROTOCOL_ERROR;
3119                 }
3120                 break;
3121
3122         case DCERPC_PKT_CO_CANCEL:
3123         case DCERPC_PKT_ORPHANED:
3124                 // TODO...
3125         default:
3126                 DEBUG(0, ("Unknown packet type %u received from %s!\n",
3127                           (unsigned int)pkt->ptype,
3128                          "TODO"));
3129                 return NT_STATUS_RPC_PROTOCOL_ERROR;
3130         }
3131
3132         // TODO check last_call_id range, here or in the main loop???
3133
3134         /* Ensure we have the correct type. */
3135         switch (pkt->ptype) {
3136         case DCERPC_PKT_BIND:
3137                 // TODO...
3138
3139                 state->conn->features.bind_done = true;
3140                 state->allow_incoming = true;
3141                 break;
3142
3143         case DCERPC_PKT_AUTH3:
3144                 // TODO...
3145
3146                 break;
3147
3148         case DCERPC_PKT_ALTER:
3149                 // TODO...
3150
3151                 break;
3152
3153         case DCERPC_PKT_REQUEST:
3154                 // TODO...
3155
3156                 break;
3157
3158         default:
3159                 return NT_STATUS_INTERNAL_ERROR;
3160         }
3161
3162         return NT_STATUS_NOT_IMPLEMENTED;
3163 }
3164
3165 NTSTATUS dcerpc_server_connection_loop_recv(struct tevent_req *req)
3166 {
3167         return tevent_req_simple_recv_ntstatus(req);
3168 }
3169