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