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