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