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