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