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