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