fix source4/librpc/rpc/dcerpc.c dcerpc_bh_raw_call_recv
[metze/samba/wip.git] / source4 / librpc / rpc / dcerpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    raw dcerpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Jelmer Vernooij 2004-2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "../lib/util/dlinklist.h"
26 #include "lib/events/events.h"
27 #include "librpc/rpc/dcerpc.h"
28 #include "librpc/rpc/dcerpc_proto.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "auth/gensec/gensec.h"
32 #include "param/param.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "librpc/rpc/rpc_common.h"
35 #include "lib/tsocket/tsocket.h"
36 #include "libcli/smb/tstream_smbXcli_np.h"
37
38
39 enum rpc_request_state {
40         RPC_REQUEST_QUEUED,
41         RPC_REQUEST_PENDING,
42         RPC_REQUEST_DONE
43 };
44
45 /*
46   handle for an async dcerpc request
47 */
48 struct rpc_request {
49         struct rpc_request *next, *prev;
50         struct dcerpc_pipe *p;
51         NTSTATUS status;
52         uint32_t call_id;
53         enum rpc_request_state state;
54         DATA_BLOB payload;
55         uint32_t flags;
56         uint32_t fault_code;
57
58         /* this is used to distinguish bind and alter_context requests
59            from normal requests */
60         void (*recv_handler)(struct rpc_request *conn, 
61                              DATA_BLOB *blob, struct ncacn_packet *pkt);
62
63         const struct GUID *object;
64         uint16_t opnum;
65         DATA_BLOB request_data;
66         bool request_data_can_append;
67         struct tevent_req *stub_subreq;
68         bool ignore_timeout;
69         bool wait_for_sync;
70         bool verify_bitmask1;
71         bool verify_pcontext;
72         bool first_pdu_done;
73         bool incomplete_request_data;
74         bool incomplete_payload;
75         bool last_pdu_done;
76
77         struct {
78                 void (*callback)(struct rpc_request *);
79                 void *private_data;
80         } async;
81 };
82
83 _PUBLIC_ NTSTATUS dcerpc_init(void)
84 {
85         return gensec_init();
86 }
87
88 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status);
89 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c);
90
91 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
92                                                struct dcerpc_pipe *p,
93                                                const struct GUID *object,
94                                                uint16_t opnum,
95                                                DATA_BLOB *stub_data);
96 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
97                                     TALLOC_CTX *mem_ctx,
98                                     DATA_BLOB *stub_data);
99 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
100                                        TALLOC_CTX *mem_ctx,
101                                        DATA_BLOB blob,
102                                        size_t struct_size,
103                                        ndr_push_flags_fn_t ndr_push,
104                                        ndr_pull_flags_fn_t ndr_pull);
105 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
106                                         struct ndr_pull *pull_in,
107                                         void *struct_ptr,
108                                         size_t struct_size,
109                                         ndr_push_flags_fn_t ndr_push,
110                                         ndr_pull_flags_fn_t ndr_pull,
111                                         ndr_print_function_t ndr_print);
112 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *p, NTSTATUS status);
113 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
114                              bool trigger_read);
115 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p);
116
117 /* destroy a dcerpc connection */
118 static int dcerpc_connection_destructor(struct dcecli_connection *conn)
119 {
120         if (conn->dead) {
121                 conn->free_skipped = true;
122                 return -1;
123         }
124         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
125         return 0;
126 }
127
128
129 /* initialise a dcerpc connection. 
130    the event context is optional
131 */
132 static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 
133                                                  struct tevent_context *ev)
134 {
135         struct dcecli_connection *c;
136
137         c = talloc_zero(mem_ctx, struct dcecli_connection);
138         if (!c) {
139                 return NULL;
140         }
141
142         c->event_ctx = ev;
143
144         if (c->event_ctx == NULL) {
145                 talloc_free(c);
146                 return NULL;
147         }
148
149         c->call_id = 1;
150         c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
151         c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
152         c->security_state.auth_context_id = 0;
153         c->security_state.session_key = dcerpc_generic_session_key;
154         c->security_state.generic_state = NULL;
155         c->flags = 0;
156         /*
157          * Windows uses 5840 for ncacn_ip_tcp,
158          * so we also use it (for every transport)
159          * by default. But we give the transport
160          * the chance to overwrite it.
161          */
162         c->srv_max_xmit_frag = 5840;
163         c->srv_max_recv_frag = 5840;
164         c->max_total_response_size = DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE;
165         c->pending = NULL;
166
167         c->io_trigger = tevent_create_immediate(c);
168         if (c->io_trigger == NULL) {
169                 talloc_free(c);
170                 return NULL;
171         }
172
173         talloc_set_destructor(c, dcerpc_connection_destructor);
174
175         return c;
176 }
177
178 struct dcerpc_bh_state {
179         struct dcerpc_pipe *p;
180 };
181
182 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
183 {
184         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
185                                      struct dcerpc_bh_state);
186
187         if (!hs->p) {
188                 return false;
189         }
190
191         if (!hs->p->conn) {
192                 return false;
193         }
194
195         if (hs->p->conn->dead) {
196                 return false;
197         }
198
199         return true;
200 }
201
202 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
203                                       uint32_t timeout)
204 {
205         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
206                                      struct dcerpc_bh_state);
207         uint32_t old;
208
209         if (!hs->p) {
210                 return DCERPC_REQUEST_TIMEOUT;
211         }
212
213         old = hs->p->request_timeout;
214         hs->p->request_timeout = timeout;
215
216         return old;
217 }
218
219 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
220                                 enum dcerpc_AuthType *auth_type,
221                                 enum dcerpc_AuthLevel *auth_level)
222 {
223         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
224                                      struct dcerpc_bh_state);
225
226         if (hs->p == NULL) {
227                 return;
228         }
229
230         if (hs->p->conn == NULL) {
231                 return;
232         }
233
234         *auth_type = hs->p->conn->security_state.auth_type;
235         *auth_level = hs->p->conn->security_state.auth_level;
236 }
237
238 struct dcerpc_bh_raw_call_state {
239         struct tevent_context *ev;
240         struct dcerpc_binding_handle *h;
241         uint32_t in_flags;
242         DATA_BLOB in_data;
243         DATA_BLOB out_data;
244         uint32_t out_flags;
245         struct rpc_request *subreq;
246 };
247
248 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
249
250 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
251                                                   struct tevent_context *ev,
252                                                   struct dcerpc_binding_handle *h,
253                                                   const struct GUID *object,
254                                                   uint32_t opnum,
255                                                   uint32_t in_flags,
256                                                   const uint8_t *in_data,
257                                                   size_t in_length)
258 {
259         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
260                                      struct dcerpc_bh_state);
261         struct tevent_req *req;
262         struct dcerpc_bh_raw_call_state *state;
263         bool ok;
264
265         req = tevent_req_create(mem_ctx, &state,
266                                 struct dcerpc_bh_raw_call_state);
267         if (req == NULL) {
268                 return NULL;
269         }
270         state->ev = ev;
271         state->h = h;
272         state->in_flags = in_flags;
273         state->in_data.data = discard_const_p(uint8_t, in_data);
274         state->in_data.length = in_length;
275
276         ok = dcerpc_bh_is_connected(h);
277         if (!ok) {
278                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
279                 return tevent_req_post(req, ev);
280         }
281
282         state->subreq = dcerpc_request_send(state,
283                                             hs->p,
284                                             object,
285                                             opnum,
286                                             &state->in_data);
287         if (tevent_req_nomem(state->subreq, req)) {
288                 return tevent_req_post(req, ev);
289         }
290         state->subreq->async.callback = dcerpc_bh_raw_call_done;
291         state->subreq->async.private_data = req;
292
293         if (state->in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
294                 state->subreq->incomplete_request_data = true;
295                 state->subreq->incomplete_payload = true;
296         }
297
298         return req;
299 }
300
301 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
302 {
303         struct tevent_req *req =
304                 talloc_get_type_abort(subreq->async.private_data,
305                 struct tevent_req);
306         struct dcerpc_bh_raw_call_state *state =
307                 tevent_req_data(req,
308                 struct dcerpc_bh_raw_call_state);
309         NTSTATUS status;
310         uint32_t fault_code;
311
312         state->out_flags = 0;
313         if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
314                 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
315         }
316
317         if (subreq->state == RPC_REQUEST_PENDING) {
318                 state->out_flags |= LIBNDR_FLAG_INCOMPLETE_BUFFER;
319         } else {
320                 state->subreq = NULL;
321                 state->out_flags &= ~LIBNDR_FLAG_INCOMPLETE_BUFFER;
322         }
323
324         fault_code = subreq->fault_code;
325
326         status = dcerpc_request_recv(subreq, state, &state->out_data);
327         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
328                 status = dcerpc_fault_to_nt_status(fault_code);
329         }
330
331         /*
332          * We trigger the callback in the next event run
333          * because the code in this file might trigger
334          * multiple request callbacks from within a single
335          * while loop.
336          *
337          * In order to avoid segfaults from within
338          * dcerpc_connection_dead() we call
339          * tevent_req_defer_callback().
340          */
341         tevent_req_defer_callback(req, state->ev);
342
343         if (!NT_STATUS_IS_OK(status)) {
344                 tevent_req_nterror(req, status);
345                 return;
346         }
347
348         if (state->out_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
349                 tevent_req_notify_callback(req);
350                 return;
351         }
352
353         tevent_req_done(req);
354 }
355
356 static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
357                                         TALLOC_CTX *mem_ctx,
358                                         uint8_t **out_data,
359                                         size_t *out_length,
360                                         uint32_t *out_flags)
361 {
362         struct dcerpc_bh_raw_call_state *state =
363                 tevent_req_data(req,
364                 struct dcerpc_bh_raw_call_state);
365         NTSTATUS status = NT_STATUS_OK;
366
367         if (!tevent_req_is_in_progress(req)) {
368                 if (tevent_req_is_nterror(req, &status)) {
369                         tevent_req_received(req);
370                         return status;
371                 }
372         }
373
374         *out_data = talloc_move(mem_ctx, &state->out_data.data);
375         *out_length = state->out_data.length;
376         *out_flags = state->out_flags;
377         if (!(state->out_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER)) {
378                 tevent_req_received(req);
379         }
380         return NT_STATUS_OK;
381 }
382
383 struct dcerpc_bh_raw_call_in_state {
384         uint8_t dummy;
385 };
386
387 static struct tevent_req *dcerpc_bh_raw_call_in_send(TALLOC_CTX *mem_ctx,
388                                         struct tevent_context *ev,
389                                         struct tevent_req *raw_call_req,
390                                         uint32_t in_flags,
391                                         const uint8_t *in_data,
392                                         size_t in_length)
393 {
394         struct dcerpc_bh_raw_call_state *raw_call_state = NULL;
395         struct tevent_req *req;
396         struct dcerpc_bh_raw_call_in_state *state;
397         struct rpc_request *rpcreq = NULL;
398         DATA_BLOB *b = NULL;
399         bool ok;
400
401         req = tevent_req_create(mem_ctx, &state,
402                                 struct dcerpc_bh_raw_call_in_state);
403         if (req == NULL) {
404                 return NULL;
405         }
406
407         if (!tevent_req_is_in_progress(raw_call_req)) {
408                 tevent_req_nterror(req, NT_STATUS_RPC_CALL_FAILED);
409                 return tevent_req_post(req, ev);
410         }
411
412         raw_call_state = tevent_req_data(raw_call_req,
413                                          struct dcerpc_bh_raw_call_state);
414
415         if (raw_call_state->subreq == NULL) {
416                 tevent_req_nterror(req, NT_STATUS_RPC_CALL_FAILED);
417                 return tevent_req_post(req, ev);
418         }
419
420         rpcreq = raw_call_state->subreq;
421
422         if (rpcreq->state != RPC_REQUEST_QUEUED) {
423                 tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION);
424                 return tevent_req_post(req, ev);
425         }
426
427         if (!(in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER)) {
428                 rpcreq->incomplete_request_data = false;
429         }
430
431         b = &rpcreq->request_data;
432
433         if (in_length == 0) {
434                 if (in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
435                         /*
436                          * with LIBNDR_FLAG_INCOMPLETE_BUFFER
437                          * we need to make sure we make any progress...
438                          */
439                         tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION);
440                         return tevent_req_post(req, ev);
441                 }
442
443                 /*
444                  * nothing to add
445                  */
446         } else if (rpcreq->request_data_can_append) {
447                 ok = data_blob_append(rpcreq, b, in_data, in_length);
448                 if (!ok) {
449                         tevent_req_nomem(NULL, req);
450                         return tevent_req_post(req, ev);
451                 }
452         } else {
453                 *b = data_blob_talloc(rpcreq, b->data, b->length);
454                 if (tevent_req_nomem(b->data, req)) {
455                         return tevent_req_post(req, ev);
456                 }
457                 rpcreq->request_data_can_append = true;
458                 ok = data_blob_append(rpcreq, b, in_data, in_length);
459                 if (!ok) {
460                         tevent_req_nomem(NULL, req);
461                         return tevent_req_post(req, ev);
462                 }
463         }
464
465         dcerpc_schedule_io_trigger(rpcreq->p->conn);
466
467         if (b->length > (rpcreq->p->conn->srv_max_xmit_frag * 10)) {
468                 rpcreq->stub_subreq = req;
469                 //TODO
470                 return req;
471         }
472
473         tevent_req_done(req);
474         return tevent_req_post(req, ev);
475 }
476
477 static NTSTATUS dcerpc_bh_raw_call_in_recv(struct tevent_req *req)
478 {
479         return tevent_req_simple_recv_ntstatus(req);
480 }
481
482 struct dcerpc_bh_disconnect_state {
483         uint8_t _dummy;
484 };
485
486 static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
487                                                 struct tevent_context *ev,
488                                                 struct dcerpc_binding_handle *h)
489 {
490         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
491                                      struct dcerpc_bh_state);
492         struct tevent_req *req;
493         struct dcerpc_bh_disconnect_state *state;
494         bool ok;
495
496         req = tevent_req_create(mem_ctx, &state,
497                                 struct dcerpc_bh_disconnect_state);
498         if (req == NULL) {
499                 return NULL;
500         }
501
502         ok = dcerpc_bh_is_connected(h);
503         if (!ok) {
504                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
505                 return tevent_req_post(req, ev);
506         }
507
508         /* TODO: do a real disconnect ... */
509         hs->p = NULL;
510
511         tevent_req_done(req);
512         return tevent_req_post(req, ev);
513 }
514
515 static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
516 {
517         NTSTATUS status;
518
519         if (tevent_req_is_nterror(req, &status)) {
520                 tevent_req_received(req);
521                 return status;
522         }
523
524         tevent_req_received(req);
525         return NT_STATUS_OK;
526 }
527
528 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
529 {
530         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
531                                      struct dcerpc_bh_state);
532
533         if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
534                 return true;
535         }
536
537         return false;
538 }
539
540 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
541 {
542         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
543                                      struct dcerpc_bh_state);
544
545         if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
546                 return true;
547         }
548
549         return false;
550 }
551
552 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
553 {
554         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
555                                      struct dcerpc_bh_state);
556
557         if (hs->p->conn->flags & DCERPC_NDR64) {
558                 return true;
559         }
560
561         return false;
562 }
563
564 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
565                                    int ndr_flags,
566                                    const void *_struct_ptr,
567                                    const struct ndr_interface_call *call)
568 {
569         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
570                                      struct dcerpc_bh_state);
571         void *struct_ptr = discard_const(_struct_ptr);
572         bool print_in = false;
573         bool print_out = false;
574
575         if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
576                 print_in = true;
577         }
578
579         if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
580                 print_out = true;
581         }
582
583         if (DEBUGLEVEL >= 11) {
584                 print_in = true;
585                 print_out = true;
586         }
587
588         if (ndr_flags & NDR_IN) {
589                 if (print_in) {
590                         ndr_print_function_debug(call->ndr_print,
591                                                  call->name,
592                                                  ndr_flags,
593                                                  struct_ptr);
594                 }
595         }
596         if (ndr_flags & NDR_OUT) {
597                 if (print_out) {
598                         ndr_print_function_debug(call->ndr_print,
599                                                  call->name,
600                                                  ndr_flags,
601                                                  struct_ptr);
602                 }
603         }
604 }
605
606 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
607                                       NTSTATUS error,
608                                       const void *struct_ptr,
609                                       const struct ndr_interface_call *call)
610 {
611         DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
612                  call->name, nt_errstr(error)));
613 }
614
615 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
616                                       NTSTATUS error,
617                                       const DATA_BLOB *blob,
618                                       const struct ndr_interface_call *call)
619 {
620         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
621                                      struct dcerpc_bh_state);
622         const uint32_t num_examples = 20;
623         uint32_t i;
624
625         DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
626                  call->name, nt_errstr(error)));
627
628         if (hs->p->conn->packet_log_dir == NULL) return;
629
630         for (i=0;i<num_examples;i++) {
631                 char *name=NULL;
632                 int ret;
633
634                 ret = asprintf(&name, "%s/rpclog/%s-out.%d",
635                                hs->p->conn->packet_log_dir,
636                                call->name, i);
637                 if (ret == -1) {
638                         return;
639                 }
640                 if (!file_exist(name)) {
641                         if (file_save(name, blob->data, blob->length)) {
642                                 DEBUG(10,("Logged rpc packet to %s\n", name));
643                         }
644                         free(name);
645                         break;
646                 }
647                 free(name);
648         }
649 }
650
651 static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
652                                           TALLOC_CTX *mem_ctx,
653                                           const DATA_BLOB *blob,
654                                           const struct ndr_interface_call *call)
655 {
656         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
657                                      struct dcerpc_bh_state);
658
659         if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
660                 NTSTATUS status;
661
662                 status = dcerpc_ndr_validate_in(hs->p->conn,
663                                                 mem_ctx,
664                                                 *blob,
665                                                 call->struct_size,
666                                                 call->ndr_push,
667                                                 call->ndr_pull);
668                 if (!NT_STATUS_IS_OK(status)) {
669                         DEBUG(0,("Validation [in] failed for %s - %s\n",
670                                  call->name, nt_errstr(status)));
671                         return status;
672                 }
673         }
674
675         DEBUG(10,("rpc request data:\n"));
676         dump_data(10, blob->data, blob->length);
677
678         return NT_STATUS_OK;
679 }
680
681 static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
682                                            struct ndr_pull *pull_in,
683                                            const void *_struct_ptr,
684                                            const struct ndr_interface_call *call)
685 {
686         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
687                                      struct dcerpc_bh_state);
688         void *struct_ptr = discard_const(_struct_ptr);
689
690         DEBUG(10,("rpc reply data:\n"));
691         dump_data(10, pull_in->data, pull_in->data_size);
692
693         if (pull_in->offset != pull_in->data_size) {
694                 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
695                          pull_in->data_size - pull_in->offset,
696                          pull_in->offset, pull_in->offset,
697                          call->name));
698                 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
699                    but it turns out that early versions of NT
700                    (specifically NT3.1) add junk onto the end of rpc
701                    packets, so if we want to interoperate at all with
702                    those versions then we need to ignore this error */
703         }
704
705         if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
706                 NTSTATUS status;
707
708                 status = dcerpc_ndr_validate_out(hs->p->conn,
709                                                  pull_in,
710                                                  struct_ptr,
711                                                  call->struct_size,
712                                                  call->ndr_push,
713                                                  call->ndr_pull,
714                                                  call->ndr_print);
715                 if (!NT_STATUS_IS_OK(status)) {
716                         DEBUG(2,("Validation [out] failed for %s - %s\n",
717                                  call->name, nt_errstr(status)));
718                         return status;
719                 }
720         }
721
722         return NT_STATUS_OK;
723 }
724
725 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
726         .name                   = "dcerpc",
727         .is_connected           = dcerpc_bh_is_connected,
728         .set_timeout            = dcerpc_bh_set_timeout,
729         .auth_info              = dcerpc_bh_auth_info,
730         .raw_call_send          = dcerpc_bh_raw_call_send,
731         .raw_call_recv          = dcerpc_bh_raw_call_recv,
732         .raw_call_in_send       = dcerpc_bh_raw_call_in_send,
733         .raw_call_in_recv       = dcerpc_bh_raw_call_in_recv,
734         .disconnect_send        = dcerpc_bh_disconnect_send,
735         .disconnect_recv        = dcerpc_bh_disconnect_recv,
736
737         .push_bigendian         = dcerpc_bh_push_bigendian,
738         .ref_alloc              = dcerpc_bh_ref_alloc,
739         .use_ndr64              = dcerpc_bh_use_ndr64,
740         .do_ndr_print           = dcerpc_bh_do_ndr_print,
741         .ndr_push_failed        = dcerpc_bh_ndr_push_failed,
742         .ndr_pull_failed        = dcerpc_bh_ndr_pull_failed,
743         .ndr_validate_in        = dcerpc_bh_ndr_validate_in,
744         .ndr_validate_out       = dcerpc_bh_ndr_validate_out,
745 };
746
747 /* initialise a dcerpc pipe. */
748 struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p,
749                                                          const struct GUID *object,
750                                                          const struct ndr_interface_table *table)
751 {
752         struct dcerpc_binding_handle *h;
753         struct dcerpc_bh_state *hs;
754
755         h = dcerpc_binding_handle_create(p,
756                                          &dcerpc_bh_ops,
757                                          object,
758                                          table,
759                                          &hs,
760                                          struct dcerpc_bh_state,
761                                          __location__);
762         if (h == NULL) {
763                 return NULL;
764         }
765         hs->p = p;
766
767         dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
768
769         return h;
770 }
771
772 /* initialise a dcerpc pipe. */
773 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
774 {
775         struct dcerpc_pipe *p;
776
777         p = talloc_zero(mem_ctx, struct dcerpc_pipe);
778         if (!p) {
779                 return NULL;
780         }
781
782         p->conn = dcerpc_connection_init(p, ev);
783         if (p->conn == NULL) {
784                 talloc_free(p);
785                 return NULL;
786         }
787
788         p->request_timeout = DCERPC_REQUEST_TIMEOUT;
789
790         if (DEBUGLVL(100)) {
791                 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
792         }
793
794         return p;
795 }
796
797
798 /* 
799    choose the next call id to use
800 */
801 static uint32_t next_call_id(struct dcecli_connection *c)
802 {
803         c->call_id++;
804         if (c->call_id == 0) {
805                 c->call_id++;
806         }
807         return c->call_id;
808 }
809
810 /**
811   setup for a ndr pull, also setting up any flags from the binding string
812 */
813 static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c, 
814                                             DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
815 {
816         struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
817
818         if (ndr == NULL) return ndr;
819
820         if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
821                 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
822         }
823
824         if (c->flags & DCERPC_NDR_REF_ALLOC) {
825                 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
826         }
827
828         if (c->flags & DCERPC_NDR64) {
829                 ndr->flags |= LIBNDR_FLAG_NDR64;
830         }
831
832         return ndr;
833 }
834
835 /* 
836    parse the authentication information on a dcerpc response packet
837 */
838 static NTSTATUS ncacn_pull_pkt_auth(struct dcecli_connection *c,
839                                     TALLOC_CTX *mem_ctx,
840                                     enum dcerpc_pkt_type ptype,
841                                     uint8_t required_flags,
842                                     uint8_t optional_flags,
843                                     uint8_t payload_offset,
844                                     DATA_BLOB *payload_and_verifier,
845                                     DATA_BLOB *raw_packet,
846                                     const struct ncacn_packet *pkt)
847 {
848         const struct dcerpc_auth tmp_auth = {
849                 .auth_type = c->security_state.auth_type,
850                 .auth_level = c->security_state.auth_level,
851                 .auth_context_id = c->security_state.auth_context_id,
852         };
853         NTSTATUS status;
854
855         status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
856                                             c->security_state.generic_state,
857                                             mem_ctx,
858                                             ptype,
859                                             required_flags,
860                                             optional_flags,
861                                             payload_offset,
862                                             payload_and_verifier,
863                                             raw_packet,
864                                             pkt);
865         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
866                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
867         }
868         if (!NT_STATUS_IS_OK(status)) {
869                 return status;
870         }
871
872         return NT_STATUS_OK;
873 }
874
875
876 /* 
877    push a dcerpc request packet into a blob, possibly signing it.
878 */
879 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c, 
880                                          DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
881                                          size_t sig_size,
882                                          struct ncacn_packet *pkt)
883 {
884         const struct dcerpc_auth tmp_auth = {
885                 .auth_type = c->security_state.auth_type,
886                 .auth_level = c->security_state.auth_level,
887                 .auth_context_id = c->security_state.auth_context_id,
888         };
889         NTSTATUS status;
890         uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
891
892         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
893                 payload_offset += 16;
894         }
895
896         status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
897                                             c->security_state.generic_state,
898                                             mem_ctx, blob,
899                                             sig_size,
900                                             payload_offset,
901                                             &pkt->u.request.stub_and_verifier,
902                                             pkt);
903         if (!NT_STATUS_IS_OK(status)) {
904                 return status;
905         }
906
907         return NT_STATUS_OK;
908 }
909
910
911 /* 
912    fill in the fixed values in a dcerpc header 
913 */
914 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
915 {
916         pkt->rpc_vers = 5;
917         pkt->rpc_vers_minor = 0;
918         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
919                 pkt->drep[0] = 0;
920         } else {
921                 pkt->drep[0] = DCERPC_DREP_LE;
922         }
923         pkt->drep[1] = 0;
924         pkt->drep[2] = 0;
925         pkt->drep[3] = 0;
926 }
927
928 /*
929   map a bind nak reason to a NTSTATUS
930 */
931 static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
932 {
933         switch (reason) {
934         case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
935                 return NT_STATUS_REVISION_MISMATCH;
936         case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
937                 return NT_STATUS_INVALID_PARAMETER;
938         default:
939                 break;
940         }
941         return NT_STATUS_UNSUCCESSFUL;
942 }
943
944 static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
945 {
946         if (ack == NULL) {
947                 return NT_STATUS_RPC_PROTOCOL_ERROR;
948         }
949
950         switch (ack->result) {
951         case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
952                 /*
953                  * We have not asked for this...
954                  */
955                 return NT_STATUS_RPC_PROTOCOL_ERROR;
956         default:
957                 break;
958         }
959
960         switch (ack->reason.value) {
961         case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
962                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
963         case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
964                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
965         default:
966                 break;
967         }
968         return NT_STATUS_UNSUCCESSFUL;
969 }
970
971 /*
972   remove requests from the pending or queued queues
973  */
974 static int dcerpc_req_dequeue(struct rpc_request *req)
975 {
976         switch (req->state) {
977         case RPC_REQUEST_QUEUED:
978                 DLIST_REMOVE(req->p->conn->request_queue, req);
979                 break;
980         case RPC_REQUEST_PENDING:
981                 DLIST_REMOVE(req->p->conn->pending, req);
982                 break;
983         case RPC_REQUEST_DONE:
984                 break;
985         }
986         return 0;
987 }
988
989
990 /*
991   mark the dcerpc connection dead. All outstanding requests get an error
992 */
993 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
994 {
995         if (conn->dead) return;
996
997         conn->dead = true;
998
999         TALLOC_FREE(conn->io_trigger);
1000         conn->io_trigger_pending = false;
1001
1002         dcerpc_shutdown_pipe(conn, status);
1003
1004         /* all pending requests get the error */
1005         while (conn->pending) {
1006                 struct rpc_request *req = conn->pending;
1007                 dcerpc_req_dequeue(req);
1008                 req->state = RPC_REQUEST_DONE;
1009                 req->status = status;
1010                 if (req->async.callback) {
1011                         req->async.callback(req);
1012                 }
1013         }       
1014
1015         /* all requests, which are not shipped */
1016         while (conn->request_queue) {
1017                 struct rpc_request *req = conn->request_queue;
1018                 dcerpc_req_dequeue(req);
1019                 req->state = RPC_REQUEST_DONE;
1020                 req->status = status;
1021                 if (req->async.callback) {
1022                         req->async.callback(req);
1023                 }
1024         }
1025
1026         talloc_set_destructor(conn, NULL);
1027         if (conn->free_skipped) {
1028                 talloc_free(conn);
1029         }
1030 }
1031
1032 /*
1033   forward declarations of the recv_data handlers for the types of
1034   packets we need to handle
1035 */
1036 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
1037                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
1038
1039 /*
1040   receive a dcerpc reply from the transport. Here we work out what
1041   type of reply it is (normal request, bind or alter context) and
1042   dispatch to the appropriate handler
1043 */
1044 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1045 {
1046         struct ncacn_packet pkt;
1047
1048         if (conn->dead) {
1049                 return;
1050         }
1051
1052         if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1053                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1054         }
1055
1056         /* the transport may be telling us of a severe error, such as
1057            a dropped socket */
1058         if (!NT_STATUS_IS_OK(status)) {
1059                 data_blob_free(blob);
1060                 dcerpc_connection_dead(conn, status);
1061                 return;
1062         }
1063
1064         /* parse the basic packet to work out what type of response this is */
1065         status = dcerpc_pull_ncacn_packet(blob->data, blob, &pkt);
1066         if (!NT_STATUS_IS_OK(status)) {
1067                 data_blob_free(blob);
1068                 dcerpc_connection_dead(conn, status);
1069                 return;
1070         }
1071
1072         dcerpc_request_recv_data(conn, blob, &pkt);
1073 }
1074
1075 /*
1076   handle timeouts of individual dcerpc requests
1077 */
1078 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
1079                                    struct timeval t, void *private_data)
1080 {
1081         struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1082
1083         if (req->ignore_timeout) {
1084                 dcerpc_req_dequeue(req);
1085                 req->state = RPC_REQUEST_DONE;
1086                 req->status = NT_STATUS_IO_TIMEOUT;
1087                 if (req->async.callback) {
1088                         req->async.callback(req);
1089                 }
1090                 return;
1091         }
1092
1093         dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1094 }
1095
1096 struct dcerpc_bind_state {
1097         struct tevent_context *ev;
1098         struct dcerpc_pipe *p;
1099 };
1100
1101 static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
1102 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1103                                      DATA_BLOB *raw_packet,
1104                                      struct ncacn_packet *pkt);
1105
1106 struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
1107                                     struct tevent_context *ev,
1108                                     struct dcerpc_pipe *p,
1109                                     const struct ndr_syntax_id *syntax,
1110                                     const struct ndr_syntax_id *transfer_syntax)
1111 {
1112         struct tevent_req *req;
1113         struct dcerpc_bind_state *state;
1114         struct ncacn_packet pkt;
1115         DATA_BLOB blob;
1116         NTSTATUS status;
1117         struct rpc_request *subreq;
1118         uint32_t flags;
1119         struct ndr_syntax_id bind_time_features;
1120
1121         bind_time_features = dcerpc_construct_bind_time_features(
1122                         DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
1123                         DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
1124
1125         req = tevent_req_create(mem_ctx, &state,
1126                                 struct dcerpc_bind_state);
1127         if (req == NULL) {
1128                 return NULL;
1129         }
1130
1131         state->ev = ev;
1132         state->p = p;
1133
1134         p->syntax = *syntax;
1135         p->transfer_syntax = *transfer_syntax;
1136
1137         flags = dcerpc_binding_get_flags(p->binding);
1138
1139         init_ncacn_hdr(p->conn, &pkt);
1140
1141         pkt.ptype = DCERPC_PKT_BIND;
1142         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1143         pkt.call_id = p->conn->call_id;
1144         pkt.auth_length = 0;
1145
1146         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1147                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1148         }
1149
1150         if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1151                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1152         }
1153
1154         pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1155         pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1156         pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1157         pkt.u.bind.num_contexts = 2;
1158         pkt.u.bind.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
1159                                                 pkt.u.bind.num_contexts);
1160         if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1161                 return tevent_req_post(req, ev);
1162         }
1163         pkt.u.bind.ctx_list[0].context_id = p->context_id;
1164         pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1165         pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1166         pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1167         pkt.u.bind.ctx_list[1].context_id = p->context_id + 1;
1168         pkt.u.bind.ctx_list[1].num_transfer_syntaxes = 1;
1169         pkt.u.bind.ctx_list[1].abstract_syntax = p->syntax;
1170         pkt.u.bind.ctx_list[1].transfer_syntaxes = &bind_time_features;
1171         pkt.u.bind.auth_info = data_blob(NULL, 0);
1172
1173         /* construct the NDR form of the packet */
1174         status = ncacn_push_auth(&blob, state, &pkt,
1175                                  p->conn->security_state.tmp_auth_info.out);
1176         if (tevent_req_nterror(req, status)) {
1177                 return tevent_req_post(req, ev);
1178         }
1179
1180         /*
1181          * we allocate a dcerpc_request so we can be in the same
1182          * request queue as normal requests
1183          */
1184         subreq = talloc_zero(state, struct rpc_request);
1185         if (tevent_req_nomem(subreq, req)) {
1186                 return tevent_req_post(req, ev);
1187         }
1188
1189         subreq->state = RPC_REQUEST_PENDING;
1190         subreq->call_id = pkt.call_id;
1191         subreq->async.private_data = req;
1192         subreq->async.callback = dcerpc_bind_fail_handler;
1193         subreq->p = p;
1194         subreq->recv_handler = dcerpc_bind_recv_handler;
1195         DLIST_ADD_END(p->conn->pending, subreq);
1196         talloc_set_destructor(subreq, dcerpc_req_dequeue);
1197
1198         status = dcerpc_send_request(p->conn, &blob, true);
1199         if (tevent_req_nterror(req, status)) {
1200                 return tevent_req_post(req, ev);
1201         }
1202
1203         tevent_add_timer(ev, subreq,
1204                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1205                          dcerpc_timeout_handler, subreq);
1206
1207         return req;
1208 }
1209
1210 static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1211 {
1212         struct tevent_req *req =
1213                 talloc_get_type_abort(subreq->async.private_data,
1214                 struct tevent_req);
1215         struct dcerpc_bind_state *state =
1216                 tevent_req_data(req,
1217                 struct dcerpc_bind_state);
1218         NTSTATUS status = subreq->status;
1219
1220         TALLOC_FREE(subreq);
1221
1222         /*
1223          * We trigger the callback in the next event run
1224          * because the code in this file might trigger
1225          * multiple request callbacks from within a single
1226          * while loop.
1227          *
1228          * In order to avoid segfaults from within
1229          * dcerpc_connection_dead() we call
1230          * tevent_req_defer_callback().
1231          */
1232         tevent_req_defer_callback(req, state->ev);
1233
1234         tevent_req_nterror(req, status);
1235 }
1236
1237 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1238                                      DATA_BLOB *raw_packet,
1239                                      struct ncacn_packet *pkt)
1240 {
1241         struct tevent_req *req =
1242                 talloc_get_type_abort(subreq->async.private_data,
1243                 struct tevent_req);
1244         struct dcerpc_bind_state *state =
1245                 tevent_req_data(req,
1246                 struct dcerpc_bind_state);
1247         struct dcecli_connection *conn = state->p->conn;
1248         struct dcecli_security *sec = &conn->security_state;
1249         struct dcerpc_binding *b = NULL;
1250         NTSTATUS status;
1251         uint32_t flags;
1252
1253         /*
1254          * Note that pkt is allocated under raw_packet->data,
1255          * while raw_packet->data is a child of subreq.
1256          */
1257         talloc_steal(state, raw_packet->data);
1258         TALLOC_FREE(subreq);
1259
1260         /*
1261          * We trigger the callback in the next event run
1262          * because the code in this file might trigger
1263          * multiple request callbacks from within a single
1264          * while loop.
1265          *
1266          * In order to avoid segfaults from within
1267          * dcerpc_connection_dead() we call
1268          * tevent_req_defer_callback().
1269          */
1270         tevent_req_defer_callback(req, state->ev);
1271
1272         if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1273                 status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1274
1275                 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1276                          pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1277
1278                 tevent_req_nterror(req, status);
1279                 return;
1280         }
1281
1282         status = dcerpc_verify_ncacn_packet_header(pkt,
1283                                         DCERPC_PKT_BIND_ACK,
1284                                         pkt->u.bind_ack.auth_info.length,
1285                                         DCERPC_PFC_FLAG_FIRST |
1286                                         DCERPC_PFC_FLAG_LAST,
1287                                         DCERPC_PFC_FLAG_CONC_MPX |
1288                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1291                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1292                 return;
1293         }
1294
1295         if (pkt->u.bind_ack.num_results < 1) {
1296                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1297                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1298                 return;
1299         }
1300
1301         if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1302                 status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1303                 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1304                          pkt->u.bind_ack.ctx_list[0].reason.value,
1305                          nt_errstr(status)));
1306                 tevent_req_nterror(req, status);
1307                 return;
1308         }
1309
1310         if (pkt->u.bind_ack.num_results >= 2) {
1311                 if (pkt->u.bind_ack.ctx_list[1].result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1312                         conn->bind_time_features = pkt->u.bind_ack.ctx_list[1].reason.negotiate;
1313                 } else {
1314                         status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[1]);
1315                         DEBUG(10,("dcerpc: bind_time_feature failed - reason %d - %s\n",
1316                                  pkt->u.bind_ack.ctx_list[1].reason.value,
1317                                  nt_errstr(status)));
1318                         status = NT_STATUS_OK;
1319                 }
1320         }
1321
1322         /*
1323          * DCE-RPC 1.1 (c706) specifies
1324          * CONST_MUST_RCV_FRAG_SIZE as 1432
1325          */
1326         if (pkt->u.bind_ack.max_xmit_frag < 1432) {
1327                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1328                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1329                 return;
1330         }
1331         if (pkt->u.bind_ack.max_recv_frag < 1432) {
1332                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1333                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1334                 return;
1335         }
1336         conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1337                                       pkt->u.bind_ack.max_xmit_frag);
1338         conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1339                                       pkt->u.bind_ack.max_recv_frag);
1340
1341         flags = dcerpc_binding_get_flags(state->p->binding);
1342
1343         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1344                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1345                         conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1346                 } else {
1347                         conn->flags &= ~DCERPC_CONCURRENT_MULTIPLEX;
1348                 }
1349         }
1350
1351         if (!(conn->flags & DCERPC_CONCURRENT_MULTIPLEX)) {
1352                 struct dcerpc_binding *pb =
1353                         discard_const_p(struct dcerpc_binding, state->p->binding);
1354                 /*
1355                  * clear DCERPC_CONCURRENT_MULTIPLEX
1356                  */
1357                 status = dcerpc_binding_set_flags(pb, 0,
1358                                                   DCERPC_CONCURRENT_MULTIPLEX);
1359                 if (tevent_req_nterror(req, status)) {
1360                         return;
1361                 }
1362         }
1363         if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1364             (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1365                 conn->flags |= DCERPC_HEADER_SIGNING;
1366         }
1367
1368         /* the bind_ack might contain a reply set of credentials */
1369         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1370                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1371                                                   &pkt->u.bind_ack.auth_info,
1372                                                   sec->tmp_auth_info.in,
1373                                                   NULL, true);
1374                 if (tevent_req_nterror(req, status)) {
1375                         return;
1376                 }
1377         }
1378
1379         /*
1380          * We're the owner of the binding, so we're allowed to modify it.
1381          */
1382         b = discard_const_p(struct dcerpc_binding, state->p->binding);
1383         status = dcerpc_binding_set_assoc_group_id(b,
1384                                                    pkt->u.bind_ack.assoc_group_id);
1385         if (tevent_req_nterror(req, status)) {
1386                 return;
1387         }
1388
1389         tevent_req_done(req);
1390 }
1391
1392 NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1393 {
1394         return tevent_req_simple_recv_ntstatus(req);
1395 }
1396
1397 /* 
1398    perform a continued bind (and auth3)
1399 */
1400 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1401                       TALLOC_CTX *mem_ctx)
1402 {
1403         struct ncacn_packet pkt;
1404         NTSTATUS status;
1405         DATA_BLOB blob;
1406         uint32_t flags;
1407
1408         flags = dcerpc_binding_get_flags(p->binding);
1409
1410         init_ncacn_hdr(p->conn, &pkt);
1411
1412         pkt.ptype = DCERPC_PKT_AUTH3;
1413         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1414         pkt.call_id = next_call_id(p->conn);
1415         pkt.auth_length = 0;
1416         pkt.u.auth3.auth_info = data_blob(NULL, 0);
1417
1418         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1419                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1420         }
1421
1422         /* construct the NDR form of the packet */
1423         status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1424                                  p->conn->security_state.tmp_auth_info.out);
1425         if (!NT_STATUS_IS_OK(status)) {
1426                 return status;
1427         }
1428
1429         /* send it on its way */
1430         status = dcerpc_send_request(p->conn, &blob, false);
1431         if (!NT_STATUS_IS_OK(status)) {
1432                 return status;
1433         }
1434
1435         return NT_STATUS_OK;    
1436 }
1437
1438
1439 /*
1440   process a fragment received from the transport layer during a
1441   request
1442
1443   This function frees the data 
1444 */
1445 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
1446                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1447 {
1448         struct rpc_request *req;
1449         unsigned int length;
1450         NTSTATUS status = NT_STATUS_OK;
1451
1452         /*
1453           if this is an authenticated connection then parse and check
1454           the auth info. We have to do this before finding the
1455           matching packet, as the request structure might have been
1456           removed due to a timeout, but if it has been we still need
1457           to run the auth routines so that we don't get the sign/seal
1458           info out of step with the server
1459         */
1460         switch (pkt->ptype) {
1461         case DCERPC_PKT_RESPONSE:
1462                 status = ncacn_pull_pkt_auth(c, raw_packet->data,
1463                                    DCERPC_PKT_RESPONSE,
1464                                    0, /* required_flags */
1465                                    DCERPC_PFC_FLAG_FIRST |
1466                                    DCERPC_PFC_FLAG_LAST,
1467                                    DCERPC_REQUEST_LENGTH,
1468                                    &pkt->u.response.stub_and_verifier,
1469                                    raw_packet, pkt);
1470                 break;
1471         default:
1472                 break;
1473         }
1474
1475         /* find the matching request */
1476         for (req=c->pending;req;req=req->next) {
1477                 if (pkt->call_id == req->call_id) break;
1478         }
1479
1480 #if 0
1481         /* useful for testing certain vendors RPC servers */
1482         if (req == NULL && c->pending && pkt->call_id == 0) {
1483                 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1484                 req = c->pending;
1485         }
1486 #endif
1487
1488         if (req == NULL) {
1489                 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1490                 data_blob_free(raw_packet);
1491                 return;
1492         }
1493
1494         talloc_steal(req, raw_packet->data);
1495
1496         if (req->recv_handler != NULL) {
1497                 dcerpc_req_dequeue(req);
1498                 req->state = RPC_REQUEST_DONE;
1499
1500                 /*
1501                  * We have to look at shipping further requests before calling
1502                  * the async function, that one might close the pipe
1503                  */
1504                 dcerpc_schedule_io_trigger(c);
1505
1506                 req->recv_handler(req, raw_packet, pkt);
1507                 return;
1508         }
1509
1510         if (pkt->ptype == DCERPC_PKT_FAULT) {
1511                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1512                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1513                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1514                         dcerpc_connection_dead(c, status);
1515                         return;
1516                 }
1517                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1518                         dcerpc_connection_dead(c, status);
1519                         return;
1520                 }
1521                 req->fault_code = pkt->u.fault.status;
1522                 req->status = NT_STATUS_NET_WRITE_FAULT;
1523                 goto req_done;
1524         }
1525
1526         if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1527                 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1528                          (int)pkt->ptype)); 
1529                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1530                 return;
1531         }
1532
1533         /* now check the status from the auth routines, and if it failed then fail
1534            this request accordingly */
1535         if (!NT_STATUS_IS_OK(status)) {
1536                 dcerpc_connection_dead(c, status);
1537                 return;
1538         }
1539
1540         if (req->state != RPC_REQUEST_PENDING) {
1541                 req->status = NT_STATUS_RPC_PROTOCOL_ERROR;
1542                 goto req_done;
1543         }
1544
1545         if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1546                 if (req->first_pdu_done) {
1547                         req->status = NT_STATUS_RPC_PROTOCOL_ERROR;
1548                         goto req_done;
1549                 }
1550                 req->first_pdu_done = true;
1551
1552                 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1553                         req->flags |= DCERPC_PULL_BIGENDIAN;
1554                 } else {
1555                         req->flags &= ~DCERPC_PULL_BIGENDIAN;
1556                 }
1557         }
1558
1559         if (!req->first_pdu_done) {
1560                 req->status = NT_STATUS_RPC_PROTOCOL_ERROR;
1561                 goto req_done;
1562         }
1563
1564         length = pkt->u.response.stub_and_verifier.length;
1565
1566         if (req->payload.length + length > c->max_total_response_size) {
1567                 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1568                          (unsigned)req->payload.length + length,
1569                          (unsigned)c->max_total_response_size));
1570                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1571                 return;
1572         }
1573
1574         if (length > 0) {
1575                 req->payload.data = talloc_realloc(req, 
1576                                                    req->payload.data, 
1577                                                    uint8_t,
1578                                                    req->payload.length + length);
1579                 if (!req->payload.data) {
1580                         req->status = NT_STATUS_NO_MEMORY;
1581                         goto req_done;
1582                 }
1583                 memcpy(req->payload.data+req->payload.length, 
1584                        pkt->u.response.stub_and_verifier.data, length);
1585                 req->payload.length += length;
1586         }
1587
1588         if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1589                 req->last_pdu_done = true;
1590         }
1591
1592         if (!req->last_pdu_done) {
1593                 data_blob_free(raw_packet);
1594                 req->status = dcerpc_send_read(c);
1595                 if (!NT_STATUS_IS_OK(req->status)) {
1596                         goto req_done;
1597                 }
1598
1599                 if (!req->incomplete_payload) {
1600                         return;
1601                 }
1602
1603                 if (req->async.callback) {
1604                         req->async.callback(req);
1605                 }
1606                 return;
1607         }
1608
1609         if (req->verify_bitmask1) {
1610                 req->p->conn->security_state.verified_bitmask1 = true;
1611         }
1612         if (req->verify_pcontext) {
1613                 req->p->verified_pcontext = true;
1614         }
1615
1616         req->incomplete_payload = false;
1617
1618 req_done:
1619         data_blob_free(raw_packet);
1620
1621         /* we've got the full payload */
1622         dcerpc_req_dequeue(req);
1623         req->state = RPC_REQUEST_DONE;
1624
1625         /*
1626          * We have to look at shipping further requests before calling
1627          * the async function, that one might close the pipe
1628          */
1629         dcerpc_schedule_io_trigger(c);
1630
1631         if (req->async.callback) {
1632                 req->async.callback(req);
1633         }
1634 }
1635
1636 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
1637
1638 /*
1639   perform the send side of a async dcerpc request
1640 */
1641 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
1642                                                struct dcerpc_pipe *p,
1643                                                const struct GUID *object,
1644                                                uint16_t opnum,
1645                                                DATA_BLOB *stub_data)
1646 {
1647         struct rpc_request *req;
1648         NTSTATUS status;
1649
1650         req = talloc_zero(mem_ctx, struct rpc_request);
1651         if (req == NULL) {
1652                 return NULL;
1653         }
1654
1655         req->p = p;
1656         req->call_id = next_call_id(p->conn);
1657         req->state = RPC_REQUEST_QUEUED;
1658
1659         if (object != NULL) {
1660                 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1661                 if (req->object == NULL) {
1662                         talloc_free(req);
1663                         return NULL;
1664                 }
1665         }
1666
1667         req->opnum = opnum;
1668
1669         if (stub_data->length > 0) {
1670                 req->request_data.length = stub_data->length;
1671                 req->request_data.data = stub_data->data;
1672         } else {
1673                 req->request_data_can_append = true;
1674         }
1675
1676         status = dcerpc_request_prepare_vt(req);
1677         if (!NT_STATUS_IS_OK(status)) {
1678                 talloc_free(req);
1679                 return NULL;
1680         }
1681
1682         DLIST_ADD_END(p->conn->request_queue, req);
1683         talloc_set_destructor(req, dcerpc_req_dequeue);
1684
1685         dcerpc_schedule_io_trigger(p->conn);
1686
1687         if (p->request_timeout) {
1688                 tevent_add_timer(p->conn->event_ctx, req,
1689                                 timeval_current_ofs(p->request_timeout, 0), 
1690                                 dcerpc_timeout_handler, req);
1691         }
1692
1693         return req;
1694 }
1695
1696 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1697 {
1698         struct dcecli_security *sec = &req->p->conn->security_state;
1699         struct dcerpc_sec_verification_trailer *t;
1700         struct dcerpc_sec_vt *c = NULL;
1701         struct ndr_push *ndr = NULL;
1702         enum ndr_err_code ndr_err;
1703
1704         if (sec->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1705                 return NT_STATUS_OK;
1706         }
1707
1708         t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1709         if (t == NULL) {
1710                 return NT_STATUS_NO_MEMORY;
1711         }
1712
1713         if (!sec->verified_bitmask1) {
1714                 t->commands = talloc_realloc(t, t->commands,
1715                                              struct dcerpc_sec_vt,
1716                                              t->count.count + 1);
1717                 if (t->commands == NULL) {
1718                         return NT_STATUS_NO_MEMORY;
1719                 }
1720                 c = &t->commands[t->count.count++];
1721                 ZERO_STRUCTP(c);
1722
1723                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1724                 if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1725                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1726                 }
1727                 req->verify_bitmask1 = true;
1728         }
1729
1730         if (!req->p->verified_pcontext) {
1731                 t->commands = talloc_realloc(t, t->commands,
1732                                              struct dcerpc_sec_vt,
1733                                              t->count.count + 1);
1734                 if (t->commands == NULL) {
1735                         return NT_STATUS_NO_MEMORY;
1736                 }
1737                 c = &t->commands[t->count.count++];
1738                 ZERO_STRUCTP(c);
1739
1740                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1741                 c->u.pcontext.abstract_syntax = req->p->syntax;
1742                 c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1743
1744                 req->verify_pcontext = true;
1745         }
1746
1747         if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1748                 t->commands = talloc_realloc(t, t->commands,
1749                                              struct dcerpc_sec_vt,
1750                                              t->count.count + 1);
1751                 if (t->commands == NULL) {
1752                         return NT_STATUS_NO_MEMORY;
1753                 }
1754                 c = &t->commands[t->count.count++];
1755                 ZERO_STRUCTP(c);
1756
1757                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1758                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1759                 if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1760                         c->u.header2.drep[0] = 0;
1761                 } else {
1762                         c->u.header2.drep[0] = DCERPC_DREP_LE;
1763                 }
1764                 c->u.header2.drep[1] = 0;
1765                 c->u.header2.drep[2] = 0;
1766                 c->u.header2.drep[3] = 0;
1767                 c->u.header2.call_id = req->call_id;
1768                 c->u.header2.context_id = req->p->context_id;
1769                 c->u.header2.opnum = req->opnum;
1770         }
1771
1772         if (t->count.count == 0) {
1773                 TALLOC_FREE(t);
1774                 return NT_STATUS_OK;
1775         }
1776
1777         c = &t->commands[t->count.count - 1];
1778         c->command |= DCERPC_SEC_VT_COMMAND_END;
1779
1780         if (DEBUGLEVEL >= 10) {
1781                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1782         }
1783
1784         ndr = ndr_push_init_ctx(req);
1785         if (ndr == NULL) {
1786                 return NT_STATUS_NO_MEMORY;
1787         }
1788
1789         /*
1790          * for now we just copy and append
1791          */
1792
1793         ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1794                                  req->request_data.length);
1795         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1796                 return ndr_map_error2ntstatus(ndr_err);
1797         }
1798
1799         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1800                                                 NDR_SCALARS | NDR_BUFFERS,
1801                                                 t);
1802         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1803                 return ndr_map_error2ntstatus(ndr_err);
1804         }
1805         req->request_data = ndr_push_blob(ndr);
1806
1807         return NT_STATUS_OK;
1808 }
1809
1810 /*
1811   Send a request using the transport
1812 */
1813
1814 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1815 {
1816         struct rpc_request *req;
1817         struct dcerpc_pipe *p;
1818         DATA_BLOB *stub_data;
1819         struct ncacn_packet pkt;
1820         DATA_BLOB blob;
1821         uint32_t remaining, chunk_size;
1822         size_t sig_size = 0;
1823         bool need_async = false;
1824         bool can_async = true;
1825         bool current_pdus_done = false;
1826
1827         req = c->request_queue;
1828         if (req == NULL) {
1829                 return;
1830         }
1831
1832         p = req->p;
1833         stub_data = &req->request_data;
1834
1835         if (c->pending) {
1836                 need_async = true;
1837         }
1838
1839         remaining = stub_data->length;
1840
1841         if ((remaining == 0) && req->incomplete_request_data) {
1842                 /*
1843                  * we're waiting for more data
1844                  */
1845                 return;
1846         }
1847
1848         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1849                 can_async = gensec_have_feature(c->security_state.generic_state,
1850                                                 GENSEC_FEATURE_ASYNC_REPLIES);
1851         }
1852
1853         if (need_async && !can_async) {
1854                 req->wait_for_sync = true;
1855                 return;
1856         }
1857
1858         init_ncacn_hdr(p->conn, &pkt);
1859
1860         /* we can write a full max_recv_frag size, minus the dcerpc
1861            request header size */
1862         chunk_size = p->conn->srv_max_recv_frag;
1863         chunk_size -= DCERPC_REQUEST_LENGTH;
1864         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1865                 size_t max_payload = chunk_size;
1866
1867                 max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1868                 max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1869
1870                 sig_size = gensec_sig_size(c->security_state.generic_state,
1871                                            max_payload);
1872                 if (sig_size) {
1873                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1874                         chunk_size -= sig_size;
1875                 }
1876         }
1877         chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1878
1879         pkt.ptype = DCERPC_PKT_REQUEST;
1880         pkt.call_id = req->call_id;
1881         pkt.auth_length = 0;
1882         pkt.pfc_flags = 0;
1883         pkt.u.request.context_id = p->context_id;
1884         pkt.u.request.opnum = req->opnum;
1885
1886         if (req->object) {
1887                 pkt.u.request.object.object = *req->object;
1888                 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1889                 chunk_size -= ndr_size_GUID(req->object,0);
1890         }
1891
1892         /* we send a series of pdus without waiting for a reply */
1893         while (!current_pdus_done) {
1894                 uint32_t chunk = MIN(chunk_size, remaining);
1895                 bool last_frag = false;
1896                 bool do_trans = false;
1897
1898                 if ((chunk == remaining) && !req->incomplete_request_data) {
1899                         last_frag = true;
1900                 }
1901
1902                 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1903
1904                 if (!req->first_pdu_done) {
1905                         req->first_pdu_done = true;
1906                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1907                 }
1908                 if (last_frag) {
1909                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1910                 }
1911
1912                 pkt.u.request.alloc_hint = remaining;
1913                 pkt.u.request.stub_and_verifier.data = stub_data->data + 
1914                         (stub_data->length - remaining);
1915                 pkt.u.request.stub_and_verifier.length = chunk;
1916
1917                 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1918                 if (!NT_STATUS_IS_OK(req->status)) {
1919                         req->state = RPC_REQUEST_DONE;
1920                         DLIST_REMOVE(c->request_queue, req);
1921                         return;
1922                 }
1923
1924                 if (last_frag && !need_async) {
1925                         do_trans = true;
1926                 }
1927
1928                 req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1929                 if (!NT_STATUS_IS_OK(req->status)) {
1930                         req->state = RPC_REQUEST_DONE;
1931                         DLIST_REMOVE(c->request_queue, req);
1932                         return;
1933                 }               
1934
1935                 if (last_frag && !do_trans) {
1936                         req->status = dcerpc_send_read(p->conn);
1937                         if (!NT_STATUS_IS_OK(req->status)) {
1938                                 req->state = RPC_REQUEST_DONE;
1939                                 DLIST_REMOVE(c->request_queue, req);
1940                                 return;
1941                         }
1942                 }
1943
1944                 remaining -= chunk;
1945                 if (remaining == 0) {
1946                         current_pdus_done = true;
1947                 }
1948                 req->last_pdu_done = last_frag;
1949         }
1950
1951         if (req->request_data_can_append) {
1952                 /*
1953                  * request_data_can_append means the blob
1954                  * is a talloc child of req
1955                  */
1956                 data_blob_free(&req->request_data);
1957         }
1958         req->request_data_can_append = true;
1959         req->request_data = data_blob_null;
1960
1961         if (req->last_pdu_done) {
1962                 DLIST_REMOVE(c->request_queue, req);
1963                 DLIST_ADD(c->pending, req);
1964                 req->state = RPC_REQUEST_PENDING;
1965                 /*
1966                  * we reuse *_pdu_done for the receive side
1967                  */
1968                 req->first_pdu_done = false;
1969                 req->last_pdu_done = false;
1970         }
1971
1972         if (req->stub_subreq != NULL) {
1973                 struct tevent_req *stub_subreq = req->stub_subreq;
1974
1975                 req->stub_subreq = NULL;
1976
1977                 tevent_req_done(stub_subreq);
1978                 return;
1979         }
1980
1981         return;
1982 }
1983
1984 static void dcerpc_io_trigger(struct tevent_context *ctx,
1985                               struct tevent_immediate *im,
1986                               void *private_data)
1987 {
1988         struct dcecli_connection *c =
1989                 talloc_get_type_abort(private_data,
1990                 struct dcecli_connection);
1991
1992         c->io_trigger_pending = false;
1993
1994         dcerpc_schedule_io_trigger(c);
1995
1996         dcerpc_ship_next_request(c);
1997 }
1998
1999 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
2000 {
2001         if (c->dead) {
2002                 return;
2003         }
2004
2005         if (c->request_queue == NULL) {
2006                 return;
2007         }
2008
2009         if (c->request_queue->wait_for_sync && c->pending) {
2010                 return;
2011         }
2012
2013         if (c->request_queue->request_data.length == 0 &&
2014             c->request_queue->incomplete_request_data)
2015         {
2016                 return;
2017         }
2018
2019         if (c->io_trigger_pending) {
2020                 return;
2021         }
2022
2023         c->io_trigger_pending = true;
2024
2025         tevent_schedule_immediate(c->io_trigger,
2026                                   c->event_ctx,
2027                                   dcerpc_io_trigger,
2028                                   c);
2029 }
2030
2031 /*
2032   perform the receive side of a async dcerpc request
2033 */
2034 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
2035                                     TALLOC_CTX *mem_ctx,
2036                                     DATA_BLOB *stub_data)
2037 {
2038         NTSTATUS status;
2039
2040         *stub_data = req->payload;
2041         req->payload = data_blob_null;
2042         status = req->status;
2043         if (stub_data->data) {
2044                 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
2045         }
2046         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
2047                 req->p->last_fault_code = req->fault_code;
2048         }
2049         if (req->state == RPC_REQUEST_PENDING) {
2050                 if (NT_STATUS_IS_OK(status)) {
2051                         return status;
2052                 }
2053         }
2054         talloc_unlink(talloc_parent(req), req);
2055         return status;
2056 }
2057
2058 /*
2059   this is a paranoid NDR validator. For every packet we push onto the wire
2060   we pull it back again, then push it again. Then we compare the raw NDR data
2061   for that to the NDR we initially generated. If they don't match then we know
2062   we must have a bug in either the pull or push side of our code
2063 */
2064 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 
2065                                        TALLOC_CTX *mem_ctx,
2066                                        DATA_BLOB blob,
2067                                        size_t struct_size,
2068                                        ndr_push_flags_fn_t ndr_push,
2069                                        ndr_pull_flags_fn_t ndr_pull)
2070 {
2071         void *st;
2072         struct ndr_pull *pull;
2073         struct ndr_push *push;
2074         DATA_BLOB blob2;
2075         enum ndr_err_code ndr_err;
2076
2077         st = talloc_size(mem_ctx, struct_size);
2078         if (!st) {
2079                 return NT_STATUS_NO_MEMORY;
2080         }
2081
2082         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2083         if (!pull) {
2084                 return NT_STATUS_NO_MEMORY;
2085         }
2086         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2087
2088         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2089                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
2090         }
2091
2092         if (c->flags & DCERPC_NDR64) {
2093                 pull->flags |= LIBNDR_FLAG_NDR64;
2094         }
2095
2096         ndr_err = ndr_pull(pull, NDR_IN, st);
2097         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2098                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2099                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2100                                          "failed input validation pull - %s",
2101                                          nt_errstr(status));
2102                 return ndr_map_error2ntstatus(ndr_err);
2103         }
2104
2105         push = ndr_push_init_ctx(mem_ctx);
2106         if (!push) {
2107                 return NT_STATUS_NO_MEMORY;
2108         }       
2109
2110         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2111                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
2112         }
2113
2114         if (c->flags & DCERPC_NDR64) {
2115                 push->flags |= LIBNDR_FLAG_NDR64;
2116         }
2117
2118         ndr_err = ndr_push(push, NDR_IN, st);
2119         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2120                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2121                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2122                                          "failed input validation push - %s",
2123                                          nt_errstr(status));
2124                 return ndr_map_error2ntstatus(ndr_err);
2125         }
2126
2127         blob2 = ndr_push_blob(push);
2128
2129         if (data_blob_cmp(&blob, &blob2) != 0) {
2130                 DEBUG(3,("original:\n"));
2131                 dump_data(3, blob.data, blob.length);
2132                 DEBUG(3,("secondary:\n"));
2133                 dump_data(3, blob2.data, blob2.length);
2134                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2135                                          "failed input validation blobs doesn't match");
2136                 return ndr_map_error2ntstatus(ndr_err);
2137         }
2138
2139         return NT_STATUS_OK;
2140 }
2141
2142 /*
2143   this is a paranoid NDR input validator. For every packet we pull
2144   from the wire we push it back again then pull and push it
2145   again. Then we compare the raw NDR data for that to the NDR we
2146   initially generated. If they don't match then we know we must have a
2147   bug in either the pull or push side of our code
2148 */
2149 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
2150                                         struct ndr_pull *pull_in,
2151                                         void *struct_ptr,
2152                                         size_t struct_size,
2153                                         ndr_push_flags_fn_t ndr_push,
2154                                         ndr_pull_flags_fn_t ndr_pull,
2155                                         ndr_print_function_t ndr_print)
2156 {
2157         void *st;
2158         struct ndr_pull *pull;
2159         struct ndr_push *push;
2160         DATA_BLOB blob, blob2;
2161         TALLOC_CTX *mem_ctx = pull_in;
2162         char *s1, *s2;
2163         enum ndr_err_code ndr_err;
2164
2165         st = talloc_size(mem_ctx, struct_size);
2166         if (!st) {
2167                 return NT_STATUS_NO_MEMORY;
2168         }
2169         memcpy(st, struct_ptr, struct_size);
2170
2171         push = ndr_push_init_ctx(mem_ctx);
2172         if (!push) {
2173                 return NT_STATUS_NO_MEMORY;
2174         }       
2175
2176         ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
2177         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2178                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2179                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2180                                          "failed output validation push - %s",
2181                                          nt_errstr(status));
2182                 return ndr_map_error2ntstatus(ndr_err);
2183         }
2184
2185         blob = ndr_push_blob(push);
2186
2187         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2188         if (!pull) {
2189                 return NT_STATUS_NO_MEMORY;
2190         }
2191
2192         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2193         ndr_err = ndr_pull(pull, NDR_OUT, st);
2194         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2195                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2196                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2197                                          "failed output validation pull - %s",
2198                                          nt_errstr(status));
2199                 return ndr_map_error2ntstatus(ndr_err);
2200         }
2201
2202         push = ndr_push_init_ctx(mem_ctx);
2203         if (!push) {
2204                 return NT_STATUS_NO_MEMORY;
2205         }       
2206
2207         ndr_err = ndr_push(push, NDR_OUT, st);
2208         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2209                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2210                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2211                                          "failed output validation push2 - %s",
2212                                          nt_errstr(status));
2213                 return ndr_map_error2ntstatus(ndr_err);
2214         }
2215
2216         blob2 = ndr_push_blob(push);
2217
2218         if (data_blob_cmp(&blob, &blob2) != 0) {
2219                 DEBUG(3,("original:\n"));
2220                 dump_data(3, blob.data, blob.length);
2221                 DEBUG(3,("secondary:\n"));
2222                 dump_data(3, blob2.data, blob2.length);
2223                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2224                                          "failed output validation blobs doesn't match");
2225                 return ndr_map_error2ntstatus(ndr_err);
2226         }
2227
2228         /* this checks the printed forms of the two structures, which effectively
2229            tests all of the value() attributes */
2230         s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
2231                                        NDR_OUT, struct_ptr);
2232         s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
2233                                        NDR_OUT, st);
2234         if (strcmp(s1, s2) != 0) {
2235 #if 1
2236                 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
2237 #else
2238                 /* this is sometimes useful */
2239                 printf("VALIDATE ERROR\n");
2240                 file_save("wire.dat", s1, strlen(s1));
2241                 file_save("gen.dat", s2, strlen(s2));
2242                 system("diff -u wire.dat gen.dat");
2243 #endif
2244                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2245                                          "failed output validation strings doesn't match");
2246                 return ndr_map_error2ntstatus(ndr_err);
2247         }
2248
2249         return NT_STATUS_OK;
2250 }
2251
2252 /*
2253   a useful function for retrieving the server name we connected to
2254 */
2255 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2256 {
2257         return p->conn ? p->conn->server_name : NULL;
2258 }
2259
2260
2261 /*
2262   get the dcerpc auth_level for a open connection
2263 */
2264 uint32_t dcerpc_auth_level(struct dcecli_connection *c) 
2265 {
2266         uint8_t auth_level;
2267
2268         if (c->flags & DCERPC_SEAL) {
2269                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2270         } else if (c->flags & DCERPC_SIGN) {
2271                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2272         } else if (c->flags & DCERPC_PACKET) {
2273                 auth_level = DCERPC_AUTH_LEVEL_PACKET;
2274         } else if (c->flags & DCERPC_CONNECT) {
2275                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2276         } else {
2277                 auth_level = DCERPC_AUTH_LEVEL_NONE;
2278         }
2279         return auth_level;
2280 }
2281
2282 struct dcerpc_alter_context_state {
2283         struct tevent_context *ev;
2284         struct dcerpc_pipe *p;
2285 };
2286
2287 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
2288 static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
2289                                               DATA_BLOB *raw_packet,
2290                                               struct ncacn_packet *pkt);
2291
2292 struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
2293                                              struct tevent_context *ev,
2294                                              struct dcerpc_pipe *p,
2295                                              const struct ndr_syntax_id *syntax,
2296                                              const struct ndr_syntax_id *transfer_syntax)
2297 {
2298         struct tevent_req *req;
2299         struct dcerpc_alter_context_state *state;
2300         struct ncacn_packet pkt;
2301         DATA_BLOB blob;
2302         NTSTATUS status;
2303         struct rpc_request *subreq;
2304         uint32_t flags;
2305
2306         req = tevent_req_create(mem_ctx, &state,
2307                                 struct dcerpc_alter_context_state);
2308         if (req == NULL) {
2309                 return NULL;
2310         }
2311
2312         state->ev = ev;
2313         state->p = p;
2314
2315         p->syntax = *syntax;
2316         p->transfer_syntax = *transfer_syntax;
2317
2318         flags = dcerpc_binding_get_flags(p->binding);
2319
2320         init_ncacn_hdr(p->conn, &pkt);
2321
2322         pkt.ptype = DCERPC_PKT_ALTER;
2323         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2324         pkt.call_id = p->conn->call_id;
2325         pkt.auth_length = 0;
2326
2327         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2328                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2329         }
2330
2331         pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2332         pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2333         pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2334         pkt.u.alter.num_contexts = 1;
2335         pkt.u.alter.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
2336                                                  pkt.u.alter.num_contexts);
2337         if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2338                 return tevent_req_post(req, ev);
2339         }
2340         pkt.u.alter.ctx_list[0].context_id = p->context_id;
2341         pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2342         pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2343         pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2344         pkt.u.alter.auth_info = data_blob(NULL, 0);
2345
2346         /* construct the NDR form of the packet */
2347         status = ncacn_push_auth(&blob, state, &pkt,
2348                                  p->conn->security_state.tmp_auth_info.out);
2349         if (tevent_req_nterror(req, status)) {
2350                 return tevent_req_post(req, ev);
2351         }
2352
2353         /*
2354          * we allocate a dcerpc_request so we can be in the same
2355          * request queue as normal requests
2356          */
2357         subreq = talloc_zero(state, struct rpc_request);
2358         if (tevent_req_nomem(subreq, req)) {
2359                 return tevent_req_post(req, ev);
2360         }
2361
2362         subreq->state = RPC_REQUEST_PENDING;
2363         subreq->call_id = pkt.call_id;
2364         subreq->async.private_data = req;
2365         subreq->async.callback = dcerpc_alter_context_fail_handler;
2366         subreq->p = p;
2367         subreq->recv_handler = dcerpc_alter_context_recv_handler;
2368         DLIST_ADD_END(p->conn->pending, subreq);
2369         talloc_set_destructor(subreq, dcerpc_req_dequeue);
2370
2371         status = dcerpc_send_request(p->conn, &blob, true);
2372         if (tevent_req_nterror(req, status)) {
2373                 return tevent_req_post(req, ev);
2374         }
2375
2376         tevent_add_timer(ev, subreq,
2377                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2378                          dcerpc_timeout_handler, subreq);
2379
2380         return req;
2381 }
2382
2383 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
2384 {
2385         struct tevent_req *req =
2386                 talloc_get_type_abort(subreq->async.private_data,
2387                 struct tevent_req);
2388         struct dcerpc_alter_context_state *state =
2389                 tevent_req_data(req,
2390                 struct dcerpc_alter_context_state);
2391         NTSTATUS status = subreq->status;
2392
2393         TALLOC_FREE(subreq);
2394
2395         /*
2396          * We trigger the callback in the next event run
2397          * because the code in this file might trigger
2398          * multiple request callbacks from within a single
2399          * while loop.
2400          *
2401          * In order to avoid segfaults from within
2402          * dcerpc_connection_dead() we call
2403          * tevent_req_defer_callback().
2404          */
2405         tevent_req_defer_callback(req, state->ev);
2406
2407         tevent_req_nterror(req, status);
2408 }
2409
2410 static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2411                                               DATA_BLOB *raw_packet,
2412                                               struct ncacn_packet *pkt)
2413 {
2414         struct tevent_req *req =
2415                 talloc_get_type_abort(subreq->async.private_data,
2416                 struct tevent_req);
2417         struct dcerpc_alter_context_state *state =
2418                 tevent_req_data(req,
2419                 struct dcerpc_alter_context_state);
2420         struct dcecli_connection *conn = state->p->conn;
2421         struct dcecli_security *sec = &conn->security_state;
2422         NTSTATUS status;
2423
2424         /*
2425          * Note that pkt is allocated under raw_packet->data,
2426          * while raw_packet->data is a child of subreq.
2427          */
2428         talloc_steal(state, raw_packet->data);
2429         TALLOC_FREE(subreq);
2430
2431         /*
2432          * We trigger the callback in the next event run
2433          * because the code in this file might trigger
2434          * multiple request callbacks from within a single
2435          * while loop.
2436          *
2437          * In order to avoid segfaults from within
2438          * dcerpc_connection_dead() we call
2439          * tevent_req_defer_callback().
2440          */
2441         tevent_req_defer_callback(req, state->ev);
2442
2443         if (pkt->ptype == DCERPC_PKT_FAULT) {
2444                 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2445                          dcerpc_errstr(state, pkt->u.fault.status)));
2446                 if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
2447                         state->p->last_fault_code = pkt->u.fault.status;
2448                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2449                 } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
2450                         state->p->last_fault_code = pkt->u.fault.status;
2451                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2452                 } else {
2453                         state->p->last_fault_code = pkt->u.fault.status;
2454                         status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2455                         tevent_req_nterror(req, status);
2456                 }
2457                 return;
2458         }
2459
2460         status = dcerpc_verify_ncacn_packet_header(pkt,
2461                                         DCERPC_PKT_ALTER_RESP,
2462                                         pkt->u.alter_resp.auth_info.length,
2463                                         DCERPC_PFC_FLAG_FIRST |
2464                                         DCERPC_PFC_FLAG_LAST,
2465                                         DCERPC_PFC_FLAG_CONC_MPX |
2466                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
2467         if (!NT_STATUS_IS_OK(status)) {
2468                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2469                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2470                 return;
2471         }
2472
2473         if (pkt->u.alter_resp.num_results != 1) {
2474                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2475                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2476                 return;
2477         }
2478
2479         if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2480                 status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2481                 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2482                          pkt->u.alter_resp.ctx_list[0].reason.value,
2483                          nt_errstr(status)));
2484                 tevent_req_nterror(req, status);
2485                 return;
2486         }
2487
2488         /* the alter_resp might contain a reply set of credentials */
2489         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2490                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2491                                                   &pkt->u.alter_resp.auth_info,
2492                                                   sec->tmp_auth_info.in,
2493                                                   NULL, true);
2494                 if (tevent_req_nterror(req, status)) {
2495                         return;
2496                 }
2497         }
2498
2499         tevent_req_done(req);
2500 }
2501
2502 NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2503 {
2504         return tevent_req_simple_recv_ntstatus(req);
2505 }
2506
2507 /* 
2508    send a dcerpc alter_context request
2509 */
2510 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 
2511                               TALLOC_CTX *mem_ctx,
2512                               const struct ndr_syntax_id *syntax,
2513                               const struct ndr_syntax_id *transfer_syntax)
2514 {
2515         struct tevent_req *subreq;
2516         struct tevent_context *ev = p->conn->event_ctx;
2517         bool ok;
2518
2519         /* TODO: create a new event context here */
2520
2521         subreq = dcerpc_alter_context_send(mem_ctx, ev,
2522                                            p, syntax, transfer_syntax);
2523         if (subreq == NULL) {
2524                 return NT_STATUS_NO_MEMORY;
2525         }
2526
2527         ok = tevent_req_poll(subreq, ev);
2528         if (!ok) {
2529                 NTSTATUS status;
2530                 status = map_nt_error_from_unix_common(errno);
2531                 return status;
2532         }
2533
2534         return dcerpc_alter_context_recv(subreq);
2535 }
2536
2537 static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2538 {
2539         if (c->transport.stream == NULL) {
2540                 return;
2541         }
2542
2543         tevent_queue_stop(c->transport.write_queue);
2544         TALLOC_FREE(c->transport.read_subreq);
2545         TALLOC_FREE(c->transport.stream);
2546
2547         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2548                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2549         }
2550
2551         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2552                 status = NT_STATUS_END_OF_FILE;
2553         }
2554
2555         dcerpc_recv_data(c, NULL, status);
2556 }
2557
2558
2559 /*
2560    shutdown SMB pipe connection
2561 */
2562 struct dcerpc_shutdown_pipe_state {
2563         struct dcecli_connection *c;
2564         NTSTATUS status;
2565 };
2566
2567 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
2568
2569 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2570 {
2571         struct dcerpc_shutdown_pipe_state *state;
2572         struct tevent_req *subreq;
2573
2574         if (c->transport.stream == NULL) {
2575                 return NT_STATUS_OK;
2576         }
2577
2578         state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2579         if (state == NULL) {
2580                 return NT_STATUS_NO_MEMORY;
2581         }
2582         state->c = c;
2583         state->status = status;
2584
2585         subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2586         if (subreq == NULL) {
2587                 return NT_STATUS_NO_MEMORY;
2588         }
2589         tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2590
2591         return status;
2592 }
2593
2594 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
2595 {
2596         struct dcerpc_shutdown_pipe_state *state =
2597                 tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
2598         struct dcecli_connection *c = state->c;
2599         NTSTATUS status = state->status;
2600         int error;
2601
2602         /*
2603          * here we ignore the return values...
2604          */
2605         tstream_disconnect_recv(subreq, &error);
2606         TALLOC_FREE(subreq);
2607
2608         TALLOC_FREE(state);
2609
2610         dcerpc_transport_dead(c, status);
2611 }
2612
2613
2614
2615 struct dcerpc_send_read_state {
2616         struct dcecli_connection *p;
2617 };
2618
2619 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2620 {
2621         struct dcecli_connection *p = state->p;
2622
2623         p->transport.read_subreq = NULL;
2624
2625         return 0;
2626 }
2627
2628 static void dcerpc_send_read_done(struct tevent_req *subreq);
2629
2630 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2631 {
2632         struct dcerpc_send_read_state *state;
2633
2634         if (p->transport.read_subreq != NULL) {
2635                 p->transport.pending_reads++;
2636                 return NT_STATUS_OK;
2637         }
2638
2639         state = talloc_zero(p, struct dcerpc_send_read_state);
2640         if (state == NULL) {
2641                 return NT_STATUS_NO_MEMORY;
2642         }
2643         state->p = p;
2644
2645         talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2646
2647         p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2648                                                           p->event_ctx,
2649                                                           p->transport.stream);
2650         if (p->transport.read_subreq == NULL) {
2651                 return NT_STATUS_NO_MEMORY;
2652         }
2653         tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2654
2655         return NT_STATUS_OK;
2656 }
2657
2658 static void dcerpc_send_read_done(struct tevent_req *subreq)
2659 {
2660         struct dcerpc_send_read_state *state =
2661                 tevent_req_callback_data(subreq,
2662                                          struct dcerpc_send_read_state);
2663         struct dcecli_connection *p = state->p;
2664         NTSTATUS status;
2665         struct ncacn_packet *pkt;
2666         DATA_BLOB blob;
2667
2668         status = dcerpc_read_ncacn_packet_recv(subreq, state,
2669                                                &pkt, &blob);
2670         TALLOC_FREE(subreq);
2671         if (!NT_STATUS_IS_OK(status)) {
2672                 TALLOC_FREE(state);
2673                 dcerpc_transport_dead(p, status);
2674                 return;
2675         }
2676
2677         /*
2678          * here we steal into thet connection context,
2679          * but p->transport.recv_data() will steal or free it again
2680          */
2681         talloc_steal(p, blob.data);
2682         TALLOC_FREE(state);
2683
2684         if (p->transport.pending_reads > 0) {
2685                 p->transport.pending_reads--;
2686
2687                 status = dcerpc_send_read(p);
2688                 if (!NT_STATUS_IS_OK(status)) {
2689                         dcerpc_transport_dead(p, status);
2690                         return;
2691                 }
2692         }
2693
2694         dcerpc_recv_data(p, &blob, NT_STATUS_OK);
2695 }
2696
2697 struct dcerpc_send_request_state {
2698         struct dcecli_connection *p;
2699         DATA_BLOB blob;
2700         struct iovec iov;
2701 };
2702
2703 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
2704 {
2705         struct dcecli_connection *p = state->p;
2706
2707         p->transport.read_subreq = NULL;
2708
2709         return 0;
2710 }
2711
2712 static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
2713 static void dcerpc_send_request_done(struct tevent_req *subreq);
2714
2715 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2716                                     bool trigger_read)
2717 {
2718         struct dcerpc_send_request_state *state;
2719         struct tevent_req *subreq;
2720         bool use_trans = trigger_read;
2721
2722         if (p->transport.stream == NULL) {
2723                 return NT_STATUS_CONNECTION_DISCONNECTED;
2724         }
2725
2726         state = talloc_zero(p, struct dcerpc_send_request_state);
2727         if (state == NULL) {
2728                 return NT_STATUS_NO_MEMORY;
2729         }
2730         state->p = p;
2731
2732         state->blob = data_blob_talloc(state, data->data, data->length);
2733         if (state->blob.data == NULL) {
2734                 TALLOC_FREE(state);
2735                 return NT_STATUS_NO_MEMORY;
2736         }
2737         state->iov.iov_base = (void *)state->blob.data;
2738         state->iov.iov_len = state->blob.length;
2739
2740         if (p->transport.read_subreq != NULL) {
2741                 use_trans = false;
2742         }
2743
2744         if (!tstream_is_smbXcli_np(p->transport.stream)) {
2745                 use_trans = false;
2746         }
2747
2748         if (use_trans) {
2749                 /*
2750                  * we need to block reads until our write is
2751                  * the next in the write queue.
2752                  */
2753                 p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2754                                                              p->transport.write_queue);
2755                 if (p->transport.read_subreq == NULL) {
2756                         TALLOC_FREE(state);
2757                         return NT_STATUS_NO_MEMORY;
2758                 }
2759                 tevent_req_set_callback(p->transport.read_subreq,
2760                                         dcerpc_send_request_wait_done,
2761                                         state);
2762
2763                 talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2764
2765                 trigger_read = false;
2766         }
2767
2768         subreq = tstream_writev_queue_send(state, p->event_ctx,
2769                                            p->transport.stream,
2770                                            p->transport.write_queue,
2771                                            &state->iov, 1);
2772         if (subreq == NULL) {
2773                 TALLOC_FREE(state);
2774                 return NT_STATUS_NO_MEMORY;
2775         }
2776         tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2777
2778         if (trigger_read) {
2779                 dcerpc_send_read(p);
2780         }
2781
2782         return NT_STATUS_OK;
2783 }
2784
2785 static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2786 {
2787         struct dcerpc_send_request_state *state =
2788                 tevent_req_callback_data(subreq,
2789                 struct dcerpc_send_request_state);
2790         struct dcecli_connection *p = state->p;
2791         NTSTATUS status;
2792         bool ok;
2793
2794         p->transport.read_subreq = NULL;
2795         talloc_set_destructor(state, NULL);
2796
2797         ok = tevent_queue_wait_recv(subreq);
2798         if (!ok) {
2799                 TALLOC_FREE(state);
2800                 dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2801                 return;
2802         }
2803
2804         if (tevent_queue_length(p->transport.write_queue) <= 2) {
2805                 status = tstream_smbXcli_np_use_trans(p->transport.stream);
2806                 if (!NT_STATUS_IS_OK(status)) {
2807                         TALLOC_FREE(state);
2808                         dcerpc_transport_dead(p, status);
2809                         return;
2810                 }
2811         }
2812
2813         /* we free subreq after tstream_cli_np_use_trans */
2814         TALLOC_FREE(subreq);
2815
2816         dcerpc_send_read(p);
2817 }
2818
2819 static void dcerpc_send_request_done(struct tevent_req *subreq)
2820 {
2821         struct dcerpc_send_request_state *state =
2822                 tevent_req_callback_data(subreq,
2823                 struct dcerpc_send_request_state);
2824         int ret;
2825         int error;
2826
2827         ret = tstream_writev_queue_recv(subreq, &error);
2828         TALLOC_FREE(subreq);
2829         if (ret == -1) {
2830                 struct dcecli_connection *p = state->p;
2831                 NTSTATUS status = map_nt_error_from_unix_common(error);
2832
2833                 TALLOC_FREE(state);
2834                 dcerpc_transport_dead(p, status);
2835                 return;
2836         }
2837
2838         TALLOC_FREE(state);
2839 }