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