gensec: Remove mem_ctx from calls that do not return memory
[nivanova/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(void)
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                                               raw_packet->data + DCERPC_REQUEST_LENGTH,
712                                               pkt->u.response.stub_and_verifier.length, 
713                                               raw_packet->data,
714                                               raw_packet->length - auth.credentials.length,
715                                               &auth.credentials);
716                 memcpy(pkt->u.response.stub_and_verifier.data,
717                        raw_packet->data + DCERPC_REQUEST_LENGTH,
718                        pkt->u.response.stub_and_verifier.length);
719                 break;
720                 
721         case DCERPC_AUTH_LEVEL_INTEGRITY:
722                 status = gensec_check_packet(c->security_state.generic_state, 
723                                              pkt->u.response.stub_and_verifier.data, 
724                                              pkt->u.response.stub_and_verifier.length, 
725                                              raw_packet->data,
726                                              raw_packet->length - auth.credentials.length,
727                                              &auth.credentials);
728                 break;
729
730         case DCERPC_AUTH_LEVEL_CONNECT:
731                 /* for now we ignore possible signatures here */
732                 status = NT_STATUS_OK;
733                 break;
734
735         default:
736                 status = NT_STATUS_INVALID_LEVEL;
737                 break;
738         }
739         
740         /* remove the indicated amount of padding */
741         if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
742                 return NT_STATUS_INFO_LENGTH_MISMATCH;
743         }
744         pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
745
746         return status;
747 }
748
749
750 /* 
751    push a dcerpc request packet into a blob, possibly signing it.
752 */
753 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c, 
754                                          DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
755                                          size_t sig_size,
756                                          struct ncacn_packet *pkt)
757 {
758         NTSTATUS status;
759         struct ndr_push *ndr;
760         DATA_BLOB creds2;
761         size_t payload_length;
762         enum ndr_err_code ndr_err;
763         size_t hdr_size = DCERPC_REQUEST_LENGTH;
764
765         /* non-signed packets are simpler */
766         if (sig_size == 0) {
767                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
768         }
769
770         switch (c->security_state.auth_info->auth_level) {
771         case DCERPC_AUTH_LEVEL_PRIVACY:
772         case DCERPC_AUTH_LEVEL_INTEGRITY:
773                 break;
774
775         case DCERPC_AUTH_LEVEL_CONNECT:
776                 /* TODO: let the gensec mech decide if it wants to generate a signature */
777                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
778
779         case DCERPC_AUTH_LEVEL_NONE:
780                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
781
782         default:
783                 return NT_STATUS_INVALID_LEVEL;
784         }
785
786         ndr = ndr_push_init_ctx(mem_ctx);
787         if (!ndr) {
788                 return NT_STATUS_NO_MEMORY;
789         }
790
791         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
792                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
793         }
794
795         if (c->flags & DCERPC_NDR64) {
796                 ndr->flags |= LIBNDR_FLAG_NDR64;
797         }
798
799         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
800                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
801                 hdr_size += 16;
802         }
803
804         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
805         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
806                 return ndr_map_error2ntstatus(ndr_err);
807         }
808
809         /* pad to 16 byte multiple in the payload portion of the
810            packet. This matches what w2k3 does. Note that we can't use
811            ndr_push_align() as that is relative to the start of the
812            whole packet, whereas w2k8 wants it relative to the start
813            of the stub */
814         c->security_state.auth_info->auth_pad_length =
815                 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
816         ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
817         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
818                 return ndr_map_error2ntstatus(ndr_err);
819         }
820
821         payload_length = pkt->u.request.stub_and_verifier.length + 
822                 c->security_state.auth_info->auth_pad_length;
823
824         /* we start without signature, it will appended later */
825         c->security_state.auth_info->credentials = data_blob(NULL,0);
826
827         /* add the auth verifier */
828         ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info);
829         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
830                 return ndr_map_error2ntstatus(ndr_err);
831         }
832
833         /* extract the whole packet as a blob */
834         *blob = ndr_push_blob(ndr);
835
836         /*
837          * Setup the frag and auth length in the packet buffer.
838          * This is needed if the GENSEC mech does AEAD signing
839          * of the packet headers. The signature itself will be
840          * appended later.
841          */
842         dcerpc_set_frag_length(blob, blob->length + sig_size);
843         dcerpc_set_auth_length(blob, sig_size);
844
845         /* sign or seal the packet */
846         switch (c->security_state.auth_info->auth_level) {
847         case DCERPC_AUTH_LEVEL_PRIVACY:
848                 status = gensec_seal_packet(c->security_state.generic_state, 
849                                             mem_ctx, 
850                                             blob->data + hdr_size,
851                                             payload_length,
852                                             blob->data,
853                                             blob->length,
854                                             &creds2);
855                 if (!NT_STATUS_IS_OK(status)) {
856                         return status;
857                 }
858                 break;
859
860         case DCERPC_AUTH_LEVEL_INTEGRITY:
861                 status = gensec_sign_packet(c->security_state.generic_state, 
862                                             mem_ctx, 
863                                             blob->data + hdr_size,
864                                             payload_length, 
865                                             blob->data,
866                                             blob->length,
867                                             &creds2);
868                 if (!NT_STATUS_IS_OK(status)) {
869                         return status;
870                 }
871                 break;
872
873         default:
874                 status = NT_STATUS_INVALID_LEVEL;
875                 break;
876         }
877
878         if (creds2.length != sig_size) {
879                 /* this means the sig_size estimate for the signature
880                    was incorrect. We have to correct the packet
881                    sizes. That means we could go over the max fragment
882                    length */
883                 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
884                         (unsigned) creds2.length,
885                         (unsigned) sig_size,
886                         (unsigned) c->security_state.auth_info->auth_pad_length,
887                         (unsigned) pkt->u.request.stub_and_verifier.length));
888                 dcerpc_set_frag_length(blob, blob->length + creds2.length);
889                 dcerpc_set_auth_length(blob, creds2.length);
890         }
891
892         if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
893                 return NT_STATUS_NO_MEMORY;
894         }
895
896         return NT_STATUS_OK;
897 }
898
899
900 /* 
901    fill in the fixed values in a dcerpc header 
902 */
903 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
904 {
905         pkt->rpc_vers = 5;
906         pkt->rpc_vers_minor = 0;
907         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
908                 pkt->drep[0] = 0;
909         } else {
910                 pkt->drep[0] = DCERPC_DREP_LE;
911         }
912         pkt->drep[1] = 0;
913         pkt->drep[2] = 0;
914         pkt->drep[3] = 0;
915 }
916
917 /*
918   map a bind nak reason to a NTSTATUS
919 */
920 static NTSTATUS dcerpc_map_reason(uint16_t reason)
921 {
922         switch (reason) {
923         case DCERPC_BIND_REASON_ASYNTAX:
924                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
925         case DCERPC_BIND_REASON_INVALID_AUTH_TYPE:
926                 return NT_STATUS_INVALID_PARAMETER;
927         }
928         return NT_STATUS_UNSUCCESSFUL;
929 }
930
931 /*
932   a bind or alter context has failed
933 */
934 static void dcerpc_composite_fail(struct rpc_request *req)
935 {
936         struct composite_context *c = talloc_get_type(req->async.private_data, 
937                                                       struct composite_context);
938         composite_error(c, req->status);
939 }
940
941 /*
942   remove requests from the pending or queued queues
943  */
944 static int dcerpc_req_dequeue(struct rpc_request *req)
945 {
946         switch (req->state) {
947         case RPC_REQUEST_QUEUED:
948                 DLIST_REMOVE(req->p->conn->request_queue, req);
949                 break;
950         case RPC_REQUEST_PENDING:
951                 DLIST_REMOVE(req->p->conn->pending, req);
952                 break;
953         case RPC_REQUEST_DONE:
954                 break;
955         }
956         return 0;
957 }
958
959
960 /*
961   mark the dcerpc connection dead. All outstanding requests get an error
962 */
963 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
964 {
965         if (conn->dead) return;
966
967         conn->dead = true;
968
969         if (conn->transport.shutdown_pipe) {
970                 conn->transport.shutdown_pipe(conn, status);
971         }
972
973         /* all pending requests get the error */
974         while (conn->pending) {
975                 struct rpc_request *req = conn->pending;
976                 dcerpc_req_dequeue(req);
977                 req->state = RPC_REQUEST_DONE;
978                 req->status = status;
979                 if (req->async.callback) {
980                         req->async.callback(req);
981                 }
982         }       
983
984         talloc_set_destructor(conn, NULL);
985         if (conn->free_skipped) {
986                 talloc_free(conn);
987         }
988 }
989
990 /*
991   forward declarations of the recv_data handlers for the types of
992   packets we need to handle
993 */
994 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
995                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
996
997 /*
998   receive a dcerpc reply from the transport. Here we work out what
999   type of reply it is (normal request, bind or alter context) and
1000   dispatch to the appropriate handler
1001 */
1002 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1003 {
1004         struct ncacn_packet pkt;
1005
1006         if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1007                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1008         }
1009
1010         /* the transport may be telling us of a severe error, such as
1011            a dropped socket */
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 data_blob_free(blob);
1014                 dcerpc_connection_dead(conn, status);
1015                 return;
1016         }
1017
1018         /* parse the basic packet to work out what type of response this is */
1019         status = ncacn_pull(conn, blob, blob->data, &pkt);
1020         if (!NT_STATUS_IS_OK(status)) {
1021                 data_blob_free(blob);
1022                 dcerpc_connection_dead(conn, status);
1023         }
1024
1025         dcerpc_request_recv_data(conn, blob, &pkt);
1026 }
1027
1028 /*
1029   Receive a bind reply from the transport
1030 */
1031 static void dcerpc_bind_recv_handler(struct rpc_request *req, 
1032                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1033 {
1034         struct composite_context *c;
1035         struct dcecli_connection *conn;
1036
1037         c = talloc_get_type(req->async.private_data, struct composite_context);
1038
1039         if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1040                 DEBUG(2,("dcerpc: bind_nak reason %d\n",
1041                          pkt->u.bind_nak.reject_reason));
1042                 composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
1043                                                      reject_reason));
1044                 return;
1045         }
1046
1047         if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
1048             (pkt->u.bind_ack.num_results == 0) ||
1049             (pkt->u.bind_ack.ctx_list[0].result != 0)) {
1050                 req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1051                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1052                 return;
1053         }
1054
1055         conn = req->p->conn;
1056
1057         conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1058         conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1059
1060         if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1061             (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1062                 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1063         }
1064
1065         if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
1066             (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1067                 conn->flags |= DCERPC_HEADER_SIGNING;
1068         }
1069
1070         /* the bind_ack might contain a reply set of credentials */
1071         if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
1072                 NTSTATUS status;
1073                 uint32_t auth_length;
1074                 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
1075                                                   conn->security_state.auth_info, &auth_length, true);
1076                 if (!NT_STATUS_IS_OK(status)) {
1077                         composite_error(c, status);
1078                         return;
1079                 }
1080         }
1081
1082         req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1083
1084         composite_done(c);
1085 }
1086
1087 /*
1088   handle timeouts of individual dcerpc requests
1089 */
1090 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
1091                                    struct timeval t, void *private_data)
1092 {
1093         struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1094
1095         if (req->ignore_timeout) {
1096                 dcerpc_req_dequeue(req);
1097                 req->state = RPC_REQUEST_DONE;
1098                 req->status = NT_STATUS_IO_TIMEOUT;
1099                 if (req->async.callback) {
1100                         req->async.callback(req);
1101                 }
1102                 return;
1103         }
1104
1105         dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1106 }
1107
1108 /*
1109   send a async dcerpc bind request
1110 */
1111 struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
1112                                            TALLOC_CTX *mem_ctx,
1113                                            const struct ndr_syntax_id *syntax,
1114                                            const struct ndr_syntax_id *transfer_syntax)
1115 {
1116         struct composite_context *c;
1117         struct ncacn_packet pkt;
1118         DATA_BLOB blob;
1119         struct rpc_request *req;
1120
1121         c = composite_create(mem_ctx,p->conn->event_ctx);
1122         if (c == NULL) return NULL;
1123
1124         c->private_data = p;
1125
1126         p->syntax = *syntax;
1127         p->transfer_syntax = *transfer_syntax;
1128
1129         init_ncacn_hdr(p->conn, &pkt);
1130
1131         pkt.ptype = DCERPC_PKT_BIND;
1132         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1133         pkt.call_id = p->conn->call_id;
1134         pkt.auth_length = 0;
1135
1136         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1137                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1138         }
1139
1140         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1141                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1142         }
1143
1144         pkt.u.bind.max_xmit_frag = 5840;
1145         pkt.u.bind.max_recv_frag = 5840;
1146         pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
1147         pkt.u.bind.num_contexts = 1;
1148         pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1149         if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
1150         pkt.u.bind.ctx_list[0].context_id = p->context_id;
1151         pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1152         pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1153         pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1154         pkt.u.bind.auth_info = data_blob(NULL, 0);
1155
1156         /* construct the NDR form of the packet */
1157         c->status = ncacn_push_auth(&blob, c, &pkt,
1158                                     p->conn->security_state.auth_info);
1159         if (!composite_is_ok(c)) return c;
1160
1161         p->conn->transport.recv_data = dcerpc_recv_data;
1162
1163         /*
1164          * we allocate a dcerpc_request so we can be in the same
1165          * request queue as normal requests
1166          */
1167         req = talloc_zero(c, struct rpc_request);
1168         if (composite_nomem(req, c)) return c;
1169
1170         req->state = RPC_REQUEST_PENDING;
1171         req->call_id = pkt.call_id;
1172         req->async.private_data = c;
1173         req->async.callback = dcerpc_composite_fail;
1174         req->p = p;
1175         req->recv_handler = dcerpc_bind_recv_handler;
1176         DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
1177         talloc_set_destructor(req, dcerpc_req_dequeue);
1178
1179         c->status = p->conn->transport.send_request(p->conn, &blob,
1180                                                     true);
1181         if (!composite_is_ok(c)) return c;
1182
1183         event_add_timed(c->event_ctx, req,
1184                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1185                         dcerpc_timeout_handler, req);
1186
1187         return c;
1188 }
1189
1190 /*
1191   recv side of async dcerpc bind request
1192 */
1193 NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
1194 {
1195         NTSTATUS result = composite_wait(ctx);
1196         talloc_free(ctx);
1197         return result;
1198 }
1199
1200 /* 
1201    perform a continued bind (and auth3)
1202 */
1203 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1204                       TALLOC_CTX *mem_ctx)
1205 {
1206         struct ncacn_packet pkt;
1207         NTSTATUS status;
1208         DATA_BLOB blob;
1209
1210         init_ncacn_hdr(p->conn, &pkt);
1211
1212         pkt.ptype = DCERPC_PKT_AUTH3;
1213         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1214         pkt.call_id = next_call_id(p->conn);
1215         pkt.auth_length = 0;
1216         pkt.u.auth3.auth_info = data_blob(NULL, 0);
1217
1218         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1219                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1220         }
1221
1222         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1223                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1224         }
1225
1226         /* construct the NDR form of the packet */
1227         status = ncacn_push_auth(&blob, mem_ctx,
1228                                  &pkt,
1229                                  p->conn->security_state.auth_info);
1230         if (!NT_STATUS_IS_OK(status)) {
1231                 return status;
1232         }
1233
1234         /* send it on its way */
1235         status = p->conn->transport.send_request(p->conn, &blob, false);
1236         if (!NT_STATUS_IS_OK(status)) {
1237                 return status;
1238         }
1239
1240         return NT_STATUS_OK;    
1241 }
1242
1243
1244 /*
1245   process a fragment received from the transport layer during a
1246   request
1247
1248   This function frees the data 
1249 */
1250 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
1251                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1252 {
1253         struct rpc_request *req;
1254         unsigned int length;
1255         NTSTATUS status = NT_STATUS_OK;
1256
1257         /*
1258           if this is an authenticated connection then parse and check
1259           the auth info. We have to do this before finding the
1260           matching packet, as the request structure might have been
1261           removed due to a timeout, but if it has been we still need
1262           to run the auth routines so that we don't get the sign/seal
1263           info out of step with the server
1264         */
1265         if (c->security_state.auth_info && c->security_state.generic_state &&
1266             pkt->ptype == DCERPC_PKT_RESPONSE) {
1267                 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1268         }
1269
1270         /* find the matching request */
1271         for (req=c->pending;req;req=req->next) {
1272                 if (pkt->call_id == req->call_id) break;
1273         }
1274
1275 #if 0
1276         /* useful for testing certain vendors RPC servers */
1277         if (req == NULL && c->pending && pkt->call_id == 0) {
1278                 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1279                 req = c->pending;
1280         }
1281 #endif
1282
1283         if (req == NULL) {
1284                 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1285                 data_blob_free(raw_packet);
1286                 return;
1287         }
1288
1289         talloc_steal(req, raw_packet->data);
1290
1291         if (req->recv_handler != NULL) {
1292                 dcerpc_req_dequeue(req);
1293                 req->state = RPC_REQUEST_DONE;
1294                 req->recv_handler(req, raw_packet, pkt);
1295                 return;
1296         }
1297
1298         if (pkt->ptype == DCERPC_PKT_FAULT) {
1299                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1300                 req->fault_code = pkt->u.fault.status;
1301                 req->status = NT_STATUS_NET_WRITE_FAULT;
1302                 goto req_done;
1303         }
1304
1305         if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1306                 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1307                          (int)pkt->ptype)); 
1308                 req->fault_code = DCERPC_FAULT_OTHER;
1309                 req->status = NT_STATUS_NET_WRITE_FAULT;
1310                 goto req_done;
1311         }
1312
1313         /* now check the status from the auth routines, and if it failed then fail
1314            this request accordingly */
1315         if (!NT_STATUS_IS_OK(status)) {
1316                 req->status = status;
1317                 goto req_done;
1318         }
1319
1320         length = pkt->u.response.stub_and_verifier.length;
1321
1322         if (length > 0) {
1323                 req->payload.data = talloc_realloc(req, 
1324                                                    req->payload.data, 
1325                                                    uint8_t,
1326                                                    req->payload.length + length);
1327                 if (!req->payload.data) {
1328                         req->status = NT_STATUS_NO_MEMORY;
1329                         goto req_done;
1330                 }
1331                 memcpy(req->payload.data+req->payload.length, 
1332                        pkt->u.response.stub_and_verifier.data, length);
1333                 req->payload.length += length;
1334         }
1335
1336         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1337                 c->transport.send_read(c);
1338                 return;
1339         }
1340
1341         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1342                 req->flags |= DCERPC_PULL_BIGENDIAN;
1343         } else {
1344                 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1345         }
1346
1347
1348 req_done:
1349         /* we've got the full payload */
1350         req->state = RPC_REQUEST_DONE;
1351         DLIST_REMOVE(c->pending, req);
1352
1353         if (c->request_queue != NULL) {
1354                 /* We have to look at shipping further requests before calling
1355                  * the async function, that one might close the pipe */
1356                 dcerpc_ship_next_request(c);
1357         }
1358
1359         if (req->async.callback) {
1360                 req->async.callback(req);
1361         }
1362 }
1363
1364 /*
1365   perform the send side of a async dcerpc request
1366 */
1367 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, 
1368                                                const struct GUID *object,
1369                                                uint16_t opnum,
1370                                                DATA_BLOB *stub_data)
1371 {
1372         struct rpc_request *req;
1373
1374         p->conn->transport.recv_data = dcerpc_recv_data;
1375
1376         req = talloc(p, struct rpc_request);
1377         if (req == NULL) {
1378                 return NULL;
1379         }
1380
1381         req->p = p;
1382         req->call_id = next_call_id(p->conn);
1383         req->status = NT_STATUS_OK;
1384         req->state = RPC_REQUEST_QUEUED;
1385         req->payload = data_blob(NULL, 0);
1386         req->flags = 0;
1387         req->fault_code = 0;
1388         req->ignore_timeout = false;
1389         req->async.callback = NULL;
1390         req->async.private_data = NULL;
1391         req->recv_handler = NULL;
1392
1393         if (object != NULL) {
1394                 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1395                 if (req->object == NULL) {
1396                         talloc_free(req);
1397                         return NULL;
1398                 }
1399         } else {
1400                 req->object = NULL;
1401         }
1402
1403         req->opnum = opnum;
1404         req->request_data.length = stub_data->length;
1405         req->request_data.data = talloc_reference(req, stub_data->data);
1406         if (req->request_data.length && req->request_data.data == NULL) {
1407                 return NULL;
1408         }
1409
1410         DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1411         talloc_set_destructor(req, dcerpc_req_dequeue);
1412
1413         dcerpc_ship_next_request(p->conn);
1414
1415         if (p->request_timeout) {
1416                 event_add_timed(dcerpc_event_context(p), req, 
1417                                 timeval_current_ofs(p->request_timeout, 0), 
1418                                 dcerpc_timeout_handler, req);
1419         }
1420
1421         return req;
1422 }
1423
1424 /*
1425   Send a request using the transport
1426 */
1427
1428 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1429 {
1430         struct rpc_request *req;
1431         struct dcerpc_pipe *p;
1432         DATA_BLOB *stub_data;
1433         struct ncacn_packet pkt;
1434         DATA_BLOB blob;
1435         uint32_t remaining, chunk_size;
1436         bool first_packet = true;
1437         size_t sig_size = 0;
1438         bool need_async = false;
1439
1440         req = c->request_queue;
1441         if (req == NULL) {
1442                 return;
1443         }
1444
1445         p = req->p;
1446         stub_data = &req->request_data;
1447
1448         if (c->pending) {
1449                 need_async = true;
1450         }
1451
1452         DLIST_REMOVE(c->request_queue, req);
1453         DLIST_ADD(c->pending, req);
1454         req->state = RPC_REQUEST_PENDING;
1455
1456         init_ncacn_hdr(p->conn, &pkt);
1457
1458         remaining = stub_data->length;
1459
1460         /* we can write a full max_recv_frag size, minus the dcerpc
1461            request header size */
1462         chunk_size = p->conn->srv_max_recv_frag;
1463         chunk_size -= DCERPC_REQUEST_LENGTH;
1464         if (c->security_state.auth_info &&
1465             c->security_state.generic_state) {
1466                 sig_size = gensec_sig_size(c->security_state.generic_state,
1467                                            p->conn->srv_max_recv_frag);
1468                 if (sig_size) {
1469                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1470                         chunk_size -= sig_size;
1471                 }
1472         }
1473         chunk_size -= (chunk_size % 16);
1474
1475         pkt.ptype = DCERPC_PKT_REQUEST;
1476         pkt.call_id = req->call_id;
1477         pkt.auth_length = 0;
1478         pkt.pfc_flags = 0;
1479         pkt.u.request.alloc_hint = remaining;
1480         pkt.u.request.context_id = p->context_id;
1481         pkt.u.request.opnum = req->opnum;
1482
1483         if (req->object) {
1484                 pkt.u.request.object.object = *req->object;
1485                 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1486                 chunk_size -= ndr_size_GUID(req->object,0);
1487         }
1488
1489         /* we send a series of pdus without waiting for a reply */
1490         while (remaining > 0 || first_packet) {
1491                 uint32_t chunk = MIN(chunk_size, remaining);
1492                 bool last_frag = false;
1493                 bool do_trans = false;
1494
1495                 first_packet = false;
1496                 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1497
1498                 if (remaining == stub_data->length) {
1499                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1500                 }
1501                 if (chunk == remaining) {
1502                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1503                         last_frag = true;
1504                 }
1505
1506                 pkt.u.request.stub_and_verifier.data = stub_data->data + 
1507                         (stub_data->length - remaining);
1508                 pkt.u.request.stub_and_verifier.length = chunk;
1509
1510                 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1511                 if (!NT_STATUS_IS_OK(req->status)) {
1512                         req->state = RPC_REQUEST_DONE;
1513                         DLIST_REMOVE(p->conn->pending, req);
1514                         return;
1515                 }
1516
1517                 if (last_frag && !need_async) {
1518                         do_trans = true;
1519                 }
1520
1521                 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans);
1522                 if (!NT_STATUS_IS_OK(req->status)) {
1523                         req->state = RPC_REQUEST_DONE;
1524                         DLIST_REMOVE(p->conn->pending, req);
1525                         return;
1526                 }               
1527
1528                 if (last_frag && !do_trans) {
1529                         req->status = p->conn->transport.send_read(p->conn);
1530                         if (!NT_STATUS_IS_OK(req->status)) {
1531                                 req->state = RPC_REQUEST_DONE;
1532                                 DLIST_REMOVE(p->conn->pending, req);
1533                                 return;
1534                         }
1535                 }
1536
1537                 remaining -= chunk;
1538         }
1539 }
1540
1541 /*
1542   return the event context for a dcerpc pipe
1543   used by callers who wish to operate asynchronously
1544 */
1545 _PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p)
1546 {
1547         return p->conn->event_ctx;
1548 }
1549
1550
1551
1552 /*
1553   perform the receive side of a async dcerpc request
1554 */
1555 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1556                                     TALLOC_CTX *mem_ctx,
1557                                     DATA_BLOB *stub_data)
1558 {
1559         NTSTATUS status;
1560
1561         while (req->state != RPC_REQUEST_DONE) {
1562                 struct tevent_context *ctx = dcerpc_event_context(req->p);
1563                 if (event_loop_once(ctx) != 0) {
1564                         return NT_STATUS_CONNECTION_DISCONNECTED;
1565                 }
1566         }
1567         *stub_data = req->payload;
1568         status = req->status;
1569         if (stub_data->data) {
1570                 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1571         }
1572         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1573                 req->p->last_fault_code = req->fault_code;
1574         }
1575         talloc_unlink(talloc_parent(req), req);
1576         return status;
1577 }
1578
1579 /*
1580   this is a paranoid NDR validator. For every packet we push onto the wire
1581   we pull it back again, then push it again. Then we compare the raw NDR data
1582   for that to the NDR we initially generated. If they don't match then we know
1583   we must have a bug in either the pull or push side of our code
1584 */
1585 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 
1586                                        TALLOC_CTX *mem_ctx,
1587                                        DATA_BLOB blob,
1588                                        size_t struct_size,
1589                                        ndr_push_flags_fn_t ndr_push,
1590                                        ndr_pull_flags_fn_t ndr_pull)
1591 {
1592         void *st;
1593         struct ndr_pull *pull;
1594         struct ndr_push *push;
1595         DATA_BLOB blob2;
1596         enum ndr_err_code ndr_err;
1597
1598         st = talloc_size(mem_ctx, struct_size);
1599         if (!st) {
1600                 return NT_STATUS_NO_MEMORY;
1601         }
1602
1603         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1604         if (!pull) {
1605                 return NT_STATUS_NO_MEMORY;
1606         }
1607         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1608
1609         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1610                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1611         }
1612
1613         if (c->flags & DCERPC_NDR64) {
1614                 pull->flags |= LIBNDR_FLAG_NDR64;
1615         }
1616
1617         ndr_err = ndr_pull(pull, NDR_IN, st);
1618         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1619                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1620                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1621                                          "failed input validation pull - %s",
1622                                          nt_errstr(status));
1623                 return ndr_map_error2ntstatus(ndr_err);
1624         }
1625
1626         push = ndr_push_init_ctx(mem_ctx);
1627         if (!push) {
1628                 return NT_STATUS_NO_MEMORY;
1629         }       
1630
1631         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1632                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1633         }
1634
1635         if (c->flags & DCERPC_NDR64) {
1636                 push->flags |= LIBNDR_FLAG_NDR64;
1637         }
1638
1639         ndr_err = ndr_push(push, NDR_IN, st);
1640         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1641                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1642                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1643                                          "failed input validation push - %s",
1644                                          nt_errstr(status));
1645                 return ndr_map_error2ntstatus(ndr_err);
1646         }
1647
1648         blob2 = ndr_push_blob(push);
1649
1650         if (data_blob_cmp(&blob, &blob2) != 0) {
1651                 DEBUG(3,("original:\n"));
1652                 dump_data(3, blob.data, blob.length);
1653                 DEBUG(3,("secondary:\n"));
1654                 dump_data(3, blob2.data, blob2.length);
1655                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1656                                          "failed input validation blobs doesn't match");
1657                 return ndr_map_error2ntstatus(ndr_err);
1658         }
1659
1660         return NT_STATUS_OK;
1661 }
1662
1663 /*
1664   this is a paranoid NDR input validator. For every packet we pull
1665   from the wire we push it back again then pull and push it
1666   again. Then we compare the raw NDR data for that to the NDR we
1667   initially generated. If they don't match then we know we must have a
1668   bug in either the pull or push side of our code
1669 */
1670 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
1671                                         struct ndr_pull *pull_in,
1672                                         void *struct_ptr,
1673                                         size_t struct_size,
1674                                         ndr_push_flags_fn_t ndr_push,
1675                                         ndr_pull_flags_fn_t ndr_pull,
1676                                         ndr_print_function_t ndr_print)
1677 {
1678         void *st;
1679         struct ndr_pull *pull;
1680         struct ndr_push *push;
1681         DATA_BLOB blob, blob2;
1682         TALLOC_CTX *mem_ctx = pull_in;
1683         char *s1, *s2;
1684         enum ndr_err_code ndr_err;
1685
1686         st = talloc_size(mem_ctx, struct_size);
1687         if (!st) {
1688                 return NT_STATUS_NO_MEMORY;
1689         }
1690         memcpy(st, struct_ptr, struct_size);
1691
1692         push = ndr_push_init_ctx(mem_ctx);
1693         if (!push) {
1694                 return NT_STATUS_NO_MEMORY;
1695         }       
1696
1697         ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1698         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1699                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1700                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1701                                          "failed output validation push - %s",
1702                                          nt_errstr(status));
1703                 return ndr_map_error2ntstatus(ndr_err);
1704         }
1705
1706         blob = ndr_push_blob(push);
1707
1708         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1709         if (!pull) {
1710                 return NT_STATUS_NO_MEMORY;
1711         }
1712
1713         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1714         ndr_err = ndr_pull(pull, NDR_OUT, st);
1715         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1716                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1717                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1718                                          "failed output validation pull - %s",
1719                                          nt_errstr(status));
1720                 return ndr_map_error2ntstatus(ndr_err);
1721         }
1722
1723         push = ndr_push_init_ctx(mem_ctx);
1724         if (!push) {
1725                 return NT_STATUS_NO_MEMORY;
1726         }       
1727
1728         ndr_err = ndr_push(push, NDR_OUT, st);
1729         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1730                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1731                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1732                                          "failed output validation push2 - %s",
1733                                          nt_errstr(status));
1734                 return ndr_map_error2ntstatus(ndr_err);
1735         }
1736
1737         blob2 = ndr_push_blob(push);
1738
1739         if (data_blob_cmp(&blob, &blob2) != 0) {
1740                 DEBUG(3,("original:\n"));
1741                 dump_data(3, blob.data, blob.length);
1742                 DEBUG(3,("secondary:\n"));
1743                 dump_data(3, blob2.data, blob2.length);
1744                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1745                                          "failed output validation blobs doesn't match");
1746                 return ndr_map_error2ntstatus(ndr_err);
1747         }
1748
1749         /* this checks the printed forms of the two structures, which effectively
1750            tests all of the value() attributes */
1751         s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
1752                                        NDR_OUT, struct_ptr);
1753         s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
1754                                        NDR_OUT, st);
1755         if (strcmp(s1, s2) != 0) {
1756 #if 1
1757                 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
1758 #else
1759                 /* this is sometimes useful */
1760                 printf("VALIDATE ERROR\n");
1761                 file_save("wire.dat", s1, strlen(s1));
1762                 file_save("gen.dat", s2, strlen(s2));
1763                 system("diff -u wire.dat gen.dat");
1764 #endif
1765                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1766                                          "failed output validation strings doesn't match");
1767                 return ndr_map_error2ntstatus(ndr_err);
1768         }
1769
1770         return NT_STATUS_OK;
1771 }
1772
1773 /*
1774   a useful function for retrieving the server name we connected to
1775 */
1776 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
1777 {
1778         if (!p->conn->transport.target_hostname) {
1779                 if (!p->conn->transport.peer_name) {
1780                         return "";
1781                 }
1782                 return p->conn->transport.peer_name(p->conn);
1783         }
1784         return p->conn->transport.target_hostname(p->conn);
1785 }
1786
1787
1788 /*
1789   get the dcerpc auth_level for a open connection
1790 */
1791 uint32_t dcerpc_auth_level(struct dcecli_connection *c) 
1792 {
1793         uint8_t auth_level;
1794
1795         if (c->flags & DCERPC_SEAL) {
1796                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1797         } else if (c->flags & DCERPC_SIGN) {
1798                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1799         } else if (c->flags & DCERPC_CONNECT) {
1800                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1801         } else {
1802                 auth_level = DCERPC_AUTH_LEVEL_NONE;
1803         }
1804         return auth_level;
1805 }
1806
1807 /*
1808   Receive an alter reply from the transport
1809 */
1810 static void dcerpc_alter_recv_handler(struct rpc_request *req,
1811                                       DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1812 {
1813         struct composite_context *c;
1814         struct dcerpc_pipe *recv_pipe;
1815
1816         c = talloc_get_type(req->async.private_data, struct composite_context);
1817         recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
1818
1819         if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
1820             pkt->u.alter_resp.num_results == 1 &&
1821             pkt->u.alter_resp.ctx_list[0].result != 0) {
1822                 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 
1823                          pkt->u.alter_resp.ctx_list[0].reason));
1824                 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
1825                 return;
1826         }
1827
1828         if (pkt->ptype == DCERPC_PKT_FAULT) {
1829                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1830                 recv_pipe->last_fault_code = pkt->u.fault.status;
1831                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1832                 return;
1833         }
1834
1835         if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
1836             pkt->u.alter_resp.num_results == 0 ||
1837             pkt->u.alter_resp.ctx_list[0].result != 0) {
1838                 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1839                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1840                 return;
1841         }
1842
1843         /* the alter_resp might contain a reply set of credentials */
1844         if (recv_pipe->conn->security_state.auth_info &&
1845             pkt->u.alter_resp.auth_info.length) {
1846                 struct dcecli_connection *conn = recv_pipe->conn;
1847                 NTSTATUS status;
1848                 uint32_t auth_length;
1849                 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
1850                                                   conn->security_state.auth_info, &auth_length, true);
1851                 if (!NT_STATUS_IS_OK(status)) {
1852                         composite_error(c, status);
1853                         return;
1854                 }
1855         }
1856
1857         composite_done(c);
1858 }
1859
1860 /* 
1861    send a dcerpc alter_context request
1862 */
1863 struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, 
1864                                                     TALLOC_CTX *mem_ctx,
1865                                                     const struct ndr_syntax_id *syntax,
1866                                                     const struct ndr_syntax_id *transfer_syntax)
1867 {
1868         struct composite_context *c;
1869         struct ncacn_packet pkt;
1870         DATA_BLOB blob;
1871         struct rpc_request *req;
1872
1873         c = composite_create(mem_ctx, p->conn->event_ctx);
1874         if (c == NULL) return NULL;
1875
1876         c->private_data = p;
1877
1878         p->syntax = *syntax;
1879         p->transfer_syntax = *transfer_syntax;
1880
1881         init_ncacn_hdr(p->conn, &pkt);
1882
1883         pkt.ptype = DCERPC_PKT_ALTER;
1884         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1885         pkt.call_id = p->conn->call_id;
1886         pkt.auth_length = 0;
1887
1888         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1889                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1890         }
1891
1892         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1893                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1894         }
1895
1896         pkt.u.alter.max_xmit_frag = 5840;
1897         pkt.u.alter.max_recv_frag = 5840;
1898         pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;
1899         pkt.u.alter.num_contexts = 1;
1900         pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);
1901         if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;
1902         pkt.u.alter.ctx_list[0].context_id = p->context_id;
1903         pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
1904         pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
1905         pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1906         pkt.u.alter.auth_info = data_blob(NULL, 0);
1907
1908         /* construct the NDR form of the packet */
1909         c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1910                                     p->conn->security_state.auth_info);
1911         if (!composite_is_ok(c)) return c;
1912
1913         p->conn->transport.recv_data = dcerpc_recv_data;
1914
1915         /*
1916          * we allocate a dcerpc_request so we can be in the same
1917          * request queue as normal requests
1918          */
1919         req = talloc_zero(c, struct rpc_request);
1920         if (composite_nomem(req, c)) return c;
1921
1922         req->state = RPC_REQUEST_PENDING;
1923         req->call_id = pkt.call_id;
1924         req->async.private_data = c;
1925         req->async.callback = dcerpc_composite_fail;
1926         req->p = p;
1927         req->recv_handler = dcerpc_alter_recv_handler;
1928         DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
1929         talloc_set_destructor(req, dcerpc_req_dequeue);
1930
1931         c->status = p->conn->transport.send_request(p->conn, &blob, true);
1932         if (!composite_is_ok(c)) return c;
1933
1934         event_add_timed(c->event_ctx, req,
1935                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1936                         dcerpc_timeout_handler, req);
1937
1938         return c;
1939 }
1940
1941 NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
1942 {
1943         NTSTATUS result = composite_wait(ctx);
1944         talloc_free(ctx);
1945         return result;
1946 }
1947
1948 /* 
1949    send a dcerpc alter_context request
1950 */
1951 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 
1952                               TALLOC_CTX *mem_ctx,
1953                               const struct ndr_syntax_id *syntax,
1954                               const struct ndr_syntax_id *transfer_syntax)
1955 {
1956         struct composite_context *creq;
1957         creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
1958         return dcerpc_alter_context_recv(creq);
1959 }
1960