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