827499155f8d8449fda59cc70d933091f6b06689
[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         bool verify_bitmask1;
69         bool verify_pcontext;
70
71         struct {
72                 void (*callback)(struct rpc_request *);
73                 void *private_data;
74         } async;
75 };
76
77 _PUBLIC_ NTSTATUS dcerpc_init(void)
78 {
79         return gensec_init();
80 }
81
82 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status);
83 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c);
84
85 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
86                                                struct dcerpc_pipe *p,
87                                                const struct GUID *object,
88                                                uint16_t opnum,
89                                                DATA_BLOB *stub_data);
90 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
91                                     TALLOC_CTX *mem_ctx,
92                                     DATA_BLOB *stub_data);
93 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
94                                        TALLOC_CTX *mem_ctx,
95                                        DATA_BLOB blob,
96                                        size_t struct_size,
97                                        ndr_push_flags_fn_t ndr_push,
98                                        ndr_pull_flags_fn_t ndr_pull);
99 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
100                                         struct ndr_pull *pull_in,
101                                         void *struct_ptr,
102                                         size_t struct_size,
103                                         ndr_push_flags_fn_t ndr_push,
104                                         ndr_pull_flags_fn_t ndr_pull,
105                                         ndr_print_function_t ndr_print);
106 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *p, NTSTATUS status);
107 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
108                              bool trigger_read);
109 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p);
110
111 /* destroy a dcerpc connection */
112 static int dcerpc_connection_destructor(struct dcecli_connection *conn)
113 {
114         if (conn->dead) {
115                 conn->free_skipped = true;
116                 return -1;
117         }
118         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
119         return 0;
120 }
121
122
123 /* initialise a dcerpc connection. 
124    the event context is optional
125 */
126 static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 
127                                                  struct tevent_context *ev)
128 {
129         struct dcecli_connection *c;
130
131         c = talloc_zero(mem_ctx, struct dcecli_connection);
132         if (!c) {
133                 return NULL;
134         }
135
136         c->event_ctx = ev;
137
138         if (c->event_ctx == NULL) {
139                 talloc_free(c);
140                 return NULL;
141         }
142
143         c->call_id = 1;
144         c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
145         c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
146         c->security_state.auth_context_id = 0;
147         c->security_state.session_key = dcerpc_generic_session_key;
148         c->security_state.generic_state = NULL;
149         c->flags = 0;
150         /*
151          * Windows uses 5840 for ncacn_ip_tcp,
152          * so we also use it (for every transport)
153          * by default. But we give the transport
154          * the chance to overwrite it.
155          */
156         c->srv_max_xmit_frag = 5840;
157         c->srv_max_recv_frag = 5840;
158         c->pending = NULL;
159
160         c->io_trigger = tevent_create_immediate(c);
161         if (c->io_trigger == NULL) {
162                 talloc_free(c);
163                 return NULL;
164         }
165
166         talloc_set_destructor(c, dcerpc_connection_destructor);
167
168         return c;
169 }
170
171 struct dcerpc_bh_state {
172         struct dcerpc_pipe *p;
173 };
174
175 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
176 {
177         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
178                                      struct dcerpc_bh_state);
179
180         if (!hs->p) {
181                 return false;
182         }
183
184         if (!hs->p->conn) {
185                 return false;
186         }
187
188         if (hs->p->conn->dead) {
189                 return false;
190         }
191
192         return true;
193 }
194
195 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
196                                       uint32_t timeout)
197 {
198         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
199                                      struct dcerpc_bh_state);
200         uint32_t old;
201
202         if (!hs->p) {
203                 return DCERPC_REQUEST_TIMEOUT;
204         }
205
206         old = hs->p->request_timeout;
207         hs->p->request_timeout = timeout;
208
209         return old;
210 }
211
212 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
213                                 enum dcerpc_AuthType *auth_type,
214                                 enum dcerpc_AuthLevel *auth_level)
215 {
216         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
217                                      struct dcerpc_bh_state);
218
219         if (hs->p == NULL) {
220                 return;
221         }
222
223         if (hs->p->conn == NULL) {
224                 return;
225         }
226
227         *auth_type = hs->p->conn->security_state.auth_type;
228         *auth_level = hs->p->conn->security_state.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         status = dcerpc_verify_ncacn_packet_header(pkt, DCERPC_PKT_RESPONSE,
745                                         pkt->u.response.stub_and_verifier.length,
746                                         0, /* required_flags */
747                                         DCERPC_PFC_FLAG_FIRST |
748                                         DCERPC_PFC_FLAG_LAST);
749         if (!NT_STATUS_IS_OK(status)) {
750                 return status;
751         }
752
753         switch (c->security_state.auth_level) {
754         case DCERPC_AUTH_LEVEL_PRIVACY:
755         case DCERPC_AUTH_LEVEL_INTEGRITY:
756                 break;
757
758         case DCERPC_AUTH_LEVEL_CONNECT:
759                 if (pkt->auth_length != 0) {
760                         break;
761                 }
762                 return NT_STATUS_OK;
763         case DCERPC_AUTH_LEVEL_NONE:
764                 if (pkt->auth_length != 0) {
765                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
766                 }
767                 return NT_STATUS_OK;
768
769         default:
770                 return NT_STATUS_INVALID_LEVEL;
771         }
772
773         if (pkt->auth_length == 0) {
774                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
775         }
776
777         if (c->security_state.generic_state == NULL) {
778                 return NT_STATUS_INTERNAL_ERROR;
779         }
780
781         status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
782                                           &pkt->u.response.stub_and_verifier,
783                                           &auth, &auth_length, false);
784         NT_STATUS_NOT_OK_RETURN(status);
785
786         pkt->u.response.stub_and_verifier.length -= auth_length;
787
788         if (auth.auth_type != c->security_state.auth_type) {
789                 return NT_STATUS_RPC_PROTOCOL_ERROR;
790         }
791
792         if (auth.auth_level != c->security_state.auth_level) {
793                 return NT_STATUS_RPC_PROTOCOL_ERROR;
794         }
795
796         if (auth.auth_context_id != c->security_state.auth_context_id) {
797                 return NT_STATUS_RPC_PROTOCOL_ERROR;
798         }
799
800         /* check signature or unseal the packet */
801         switch (c->security_state.auth_level) {
802         case DCERPC_AUTH_LEVEL_PRIVACY:
803                 status = gensec_unseal_packet(c->security_state.generic_state, 
804                                               raw_packet->data + DCERPC_REQUEST_LENGTH,
805                                               pkt->u.response.stub_and_verifier.length, 
806                                               raw_packet->data,
807                                               raw_packet->length - auth.credentials.length,
808                                               &auth.credentials);
809                 memcpy(pkt->u.response.stub_and_verifier.data,
810                        raw_packet->data + DCERPC_REQUEST_LENGTH,
811                        pkt->u.response.stub_and_verifier.length);
812                 break;
813                 
814         case DCERPC_AUTH_LEVEL_INTEGRITY:
815                 status = gensec_check_packet(c->security_state.generic_state, 
816                                              pkt->u.response.stub_and_verifier.data, 
817                                              pkt->u.response.stub_and_verifier.length, 
818                                              raw_packet->data,
819                                              raw_packet->length - auth.credentials.length,
820                                              &auth.credentials);
821                 break;
822
823         case DCERPC_AUTH_LEVEL_CONNECT:
824                 /* for now we ignore possible signatures here */
825                 status = NT_STATUS_OK;
826                 break;
827
828         default:
829                 status = NT_STATUS_INVALID_LEVEL;
830                 break;
831         }
832         
833         /* remove the indicated amount of padding */
834         if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
835                 return NT_STATUS_INFO_LENGTH_MISMATCH;
836         }
837         pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
838
839         return status;
840 }
841
842
843 /* 
844    push a dcerpc request packet into a blob, possibly signing it.
845 */
846 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c, 
847                                          DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
848                                          size_t sig_size,
849                                          struct ncacn_packet *pkt)
850 {
851         NTSTATUS status;
852         struct ndr_push *ndr;
853         DATA_BLOB creds2;
854         size_t payload_length;
855         enum ndr_err_code ndr_err;
856         size_t hdr_size = DCERPC_REQUEST_LENGTH;
857         struct dcerpc_auth auth_info = {
858                 .auth_type = c->security_state.auth_type,
859                 .auth_level = c->security_state.auth_level,
860                 .auth_context_id = c->security_state.auth_context_id,
861         };
862
863         switch (c->security_state.auth_level) {
864         case DCERPC_AUTH_LEVEL_PRIVACY:
865         case DCERPC_AUTH_LEVEL_INTEGRITY:
866                 if (sig_size == 0) {
867                         return NT_STATUS_INTERNAL_ERROR;
868                 }
869                 break;
870
871         case DCERPC_AUTH_LEVEL_CONNECT:
872                 /* TODO: let the gensec mech decide if it wants to generate a signature */
873                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
874
875         case DCERPC_AUTH_LEVEL_NONE:
876                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
877
878         default:
879                 return NT_STATUS_INVALID_LEVEL;
880         }
881
882         ndr = ndr_push_init_ctx(mem_ctx);
883         if (!ndr) {
884                 return NT_STATUS_NO_MEMORY;
885         }
886
887         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
888                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
889         }
890
891         if (c->flags & DCERPC_NDR64) {
892                 ndr->flags |= LIBNDR_FLAG_NDR64;
893         }
894
895         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
896                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
897                 hdr_size += 16;
898         }
899
900         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
901         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
902                 return ndr_map_error2ntstatus(ndr_err);
903         }
904
905         /* pad to 16 byte multiple in the payload portion of the
906            packet. This matches what w2k3 does. Note that we can't use
907            ndr_push_align() as that is relative to the start of the
908            whole packet, whereas w2k8 wants it relative to the start
909            of the stub */
910         auth_info.auth_pad_length =
911                 DCERPC_AUTH_PAD_LENGTH(pkt->u.request.stub_and_verifier.length);
912         ndr_err = ndr_push_zero(ndr, auth_info.auth_pad_length);
913         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
914                 return ndr_map_error2ntstatus(ndr_err);
915         }
916
917         payload_length = pkt->u.request.stub_and_verifier.length + 
918                 auth_info.auth_pad_length;
919
920         /* add the auth verifier */
921         ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth_info);
922         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
923                 return ndr_map_error2ntstatus(ndr_err);
924         }
925
926         /* extract the whole packet as a blob */
927         *blob = ndr_push_blob(ndr);
928
929         /*
930          * Setup the frag and auth length in the packet buffer.
931          * This is needed if the GENSEC mech does AEAD signing
932          * of the packet headers. The signature itself will be
933          * appended later.
934          */
935         dcerpc_set_frag_length(blob, blob->length + sig_size);
936         dcerpc_set_auth_length(blob, sig_size);
937
938         /* sign or seal the packet */
939         switch (c->security_state.auth_level) {
940         case DCERPC_AUTH_LEVEL_PRIVACY:
941                 status = gensec_seal_packet(c->security_state.generic_state, 
942                                             mem_ctx, 
943                                             blob->data + hdr_size,
944                                             payload_length,
945                                             blob->data,
946                                             blob->length,
947                                             &creds2);
948                 if (!NT_STATUS_IS_OK(status)) {
949                         return status;
950                 }
951                 break;
952
953         case DCERPC_AUTH_LEVEL_INTEGRITY:
954                 status = gensec_sign_packet(c->security_state.generic_state, 
955                                             mem_ctx, 
956                                             blob->data + hdr_size,
957                                             payload_length, 
958                                             blob->data,
959                                             blob->length,
960                                             &creds2);
961                 if (!NT_STATUS_IS_OK(status)) {
962                         return status;
963                 }
964                 break;
965
966         default:
967                 status = NT_STATUS_INVALID_LEVEL;
968                 break;
969         }
970
971         if (creds2.length != sig_size) {
972                 /* this means the sig_size estimate for the signature
973                    was incorrect. We have to correct the packet
974                    sizes. That means we could go over the max fragment
975                    length */
976                 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
977                         (unsigned) creds2.length,
978                         (unsigned) sig_size,
979                         (unsigned) auth_info.auth_pad_length,
980                         (unsigned) pkt->u.request.stub_and_verifier.length));
981                 dcerpc_set_frag_length(blob, blob->length + creds2.length);
982                 dcerpc_set_auth_length(blob, creds2.length);
983         }
984
985         if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
986                 return NT_STATUS_NO_MEMORY;
987         }
988
989         return NT_STATUS_OK;
990 }
991
992
993 /* 
994    fill in the fixed values in a dcerpc header 
995 */
996 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
997 {
998         pkt->rpc_vers = 5;
999         pkt->rpc_vers_minor = 0;
1000         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1001                 pkt->drep[0] = 0;
1002         } else {
1003                 pkt->drep[0] = DCERPC_DREP_LE;
1004         }
1005         pkt->drep[1] = 0;
1006         pkt->drep[2] = 0;
1007         pkt->drep[3] = 0;
1008 }
1009
1010 /*
1011   map a bind nak reason to a NTSTATUS
1012 */
1013 static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
1014 {
1015         switch (reason) {
1016         case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
1017                 return NT_STATUS_REVISION_MISMATCH;
1018         case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
1019                 return NT_STATUS_INVALID_PARAMETER;
1020         default:
1021                 break;
1022         }
1023         return NT_STATUS_UNSUCCESSFUL;
1024 }
1025
1026 static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
1027 {
1028         if (ack == NULL) {
1029                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1030         }
1031
1032         switch (ack->result) {
1033         case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1034                 /*
1035                  * We have not asked for this...
1036                  */
1037                 return NT_STATUS_RPC_PROTOCOL_ERROR;
1038         default:
1039                 break;
1040         }
1041
1042         switch (ack->reason.value) {
1043         case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
1044                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1045         case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
1046                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1047         default:
1048                 break;
1049         }
1050         return NT_STATUS_UNSUCCESSFUL;
1051 }
1052
1053 /*
1054   remove requests from the pending or queued queues
1055  */
1056 static int dcerpc_req_dequeue(struct rpc_request *req)
1057 {
1058         switch (req->state) {
1059         case RPC_REQUEST_QUEUED:
1060                 DLIST_REMOVE(req->p->conn->request_queue, req);
1061                 break;
1062         case RPC_REQUEST_PENDING:
1063                 DLIST_REMOVE(req->p->conn->pending, req);
1064                 break;
1065         case RPC_REQUEST_DONE:
1066                 break;
1067         }
1068         return 0;
1069 }
1070
1071
1072 /*
1073   mark the dcerpc connection dead. All outstanding requests get an error
1074 */
1075 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
1076 {
1077         if (conn->dead) return;
1078
1079         conn->dead = true;
1080
1081         TALLOC_FREE(conn->io_trigger);
1082         conn->io_trigger_pending = false;
1083
1084         dcerpc_shutdown_pipe(conn, status);
1085
1086         /* all pending requests get the error */
1087         while (conn->pending) {
1088                 struct rpc_request *req = conn->pending;
1089                 dcerpc_req_dequeue(req);
1090                 req->state = RPC_REQUEST_DONE;
1091                 req->status = status;
1092                 if (req->async.callback) {
1093                         req->async.callback(req);
1094                 }
1095         }       
1096
1097         /* all requests, which are not shipped */
1098         while (conn->request_queue) {
1099                 struct rpc_request *req = conn->request_queue;
1100                 dcerpc_req_dequeue(req);
1101                 req->state = RPC_REQUEST_DONE;
1102                 req->status = status;
1103                 if (req->async.callback) {
1104                         req->async.callback(req);
1105                 }
1106         }
1107
1108         talloc_set_destructor(conn, NULL);
1109         if (conn->free_skipped) {
1110                 talloc_free(conn);
1111         }
1112 }
1113
1114 /*
1115   forward declarations of the recv_data handlers for the types of
1116   packets we need to handle
1117 */
1118 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
1119                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
1120
1121 /*
1122   receive a dcerpc reply from the transport. Here we work out what
1123   type of reply it is (normal request, bind or alter context) and
1124   dispatch to the appropriate handler
1125 */
1126 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1127 {
1128         struct ncacn_packet pkt;
1129
1130         if (conn->dead) {
1131                 return;
1132         }
1133
1134         if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1135                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1136         }
1137
1138         /* the transport may be telling us of a severe error, such as
1139            a dropped socket */
1140         if (!NT_STATUS_IS_OK(status)) {
1141                 data_blob_free(blob);
1142                 dcerpc_connection_dead(conn, status);
1143                 return;
1144         }
1145
1146         /* parse the basic packet to work out what type of response this is */
1147         status = ncacn_pull(conn, blob, blob->data, &pkt);
1148         if (!NT_STATUS_IS_OK(status)) {
1149                 data_blob_free(blob);
1150                 dcerpc_connection_dead(conn, status);
1151                 return;
1152         }
1153
1154         dcerpc_request_recv_data(conn, blob, &pkt);
1155 }
1156
1157 /*
1158   handle timeouts of individual dcerpc requests
1159 */
1160 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
1161                                    struct timeval t, void *private_data)
1162 {
1163         struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1164
1165         if (req->ignore_timeout) {
1166                 dcerpc_req_dequeue(req);
1167                 req->state = RPC_REQUEST_DONE;
1168                 req->status = NT_STATUS_IO_TIMEOUT;
1169                 if (req->async.callback) {
1170                         req->async.callback(req);
1171                 }
1172                 return;
1173         }
1174
1175         dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1176 }
1177
1178 struct dcerpc_bind_state {
1179         struct tevent_context *ev;
1180         struct dcerpc_pipe *p;
1181 };
1182
1183 static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
1184 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1185                                      DATA_BLOB *raw_packet,
1186                                      struct ncacn_packet *pkt);
1187
1188 struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
1189                                     struct tevent_context *ev,
1190                                     struct dcerpc_pipe *p,
1191                                     const struct ndr_syntax_id *syntax,
1192                                     const struct ndr_syntax_id *transfer_syntax)
1193 {
1194         struct tevent_req *req;
1195         struct dcerpc_bind_state *state;
1196         struct ncacn_packet pkt;
1197         DATA_BLOB blob;
1198         NTSTATUS status;
1199         struct rpc_request *subreq;
1200         uint32_t flags;
1201
1202         req = tevent_req_create(mem_ctx, &state,
1203                                 struct dcerpc_bind_state);
1204         if (req == NULL) {
1205                 return NULL;
1206         }
1207
1208         state->ev = ev;
1209         state->p = p;
1210
1211         p->syntax = *syntax;
1212         p->transfer_syntax = *transfer_syntax;
1213
1214         flags = dcerpc_binding_get_flags(p->binding);
1215
1216         init_ncacn_hdr(p->conn, &pkt);
1217
1218         pkt.ptype = DCERPC_PKT_BIND;
1219         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1220         pkt.call_id = p->conn->call_id;
1221         pkt.auth_length = 0;
1222
1223         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1224                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1225         }
1226
1227         if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1228                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1229         }
1230
1231         pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1232         pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1233         pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1234         pkt.u.bind.num_contexts = 1;
1235         pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1236         if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1237                 return tevent_req_post(req, ev);
1238         }
1239         pkt.u.bind.ctx_list[0].context_id = p->context_id;
1240         pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1241         pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1242         pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1243         pkt.u.bind.auth_info = data_blob(NULL, 0);
1244
1245         /* construct the NDR form of the packet */
1246         status = ncacn_push_auth(&blob, state, &pkt,
1247                                  p->conn->security_state.tmp_auth_info.out);
1248         if (tevent_req_nterror(req, status)) {
1249                 return tevent_req_post(req, ev);
1250         }
1251
1252         /*
1253          * we allocate a dcerpc_request so we can be in the same
1254          * request queue as normal requests
1255          */
1256         subreq = talloc_zero(state, struct rpc_request);
1257         if (tevent_req_nomem(subreq, req)) {
1258                 return tevent_req_post(req, ev);
1259         }
1260
1261         subreq->state = RPC_REQUEST_PENDING;
1262         subreq->call_id = pkt.call_id;
1263         subreq->async.private_data = req;
1264         subreq->async.callback = dcerpc_bind_fail_handler;
1265         subreq->p = p;
1266         subreq->recv_handler = dcerpc_bind_recv_handler;
1267         DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
1268         talloc_set_destructor(subreq, dcerpc_req_dequeue);
1269
1270         status = dcerpc_send_request(p->conn, &blob, true);
1271         if (tevent_req_nterror(req, status)) {
1272                 return tevent_req_post(req, ev);
1273         }
1274
1275         tevent_add_timer(ev, subreq,
1276                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1277                          dcerpc_timeout_handler, subreq);
1278
1279         return req;
1280 }
1281
1282 static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1283 {
1284         struct tevent_req *req =
1285                 talloc_get_type_abort(subreq->async.private_data,
1286                 struct tevent_req);
1287         struct dcerpc_bind_state *state =
1288                 tevent_req_data(req,
1289                 struct dcerpc_bind_state);
1290         NTSTATUS status = subreq->status;
1291
1292         TALLOC_FREE(subreq);
1293
1294         /*
1295          * We trigger the callback in the next event run
1296          * because the code in this file might trigger
1297          * multiple request callbacks from within a single
1298          * while loop.
1299          *
1300          * In order to avoid segfaults from within
1301          * dcerpc_connection_dead() we call
1302          * tevent_req_defer_callback().
1303          */
1304         tevent_req_defer_callback(req, state->ev);
1305
1306         tevent_req_nterror(req, status);
1307 }
1308
1309 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1310                                      DATA_BLOB *raw_packet,
1311                                      struct ncacn_packet *pkt)
1312 {
1313         struct tevent_req *req =
1314                 talloc_get_type_abort(subreq->async.private_data,
1315                 struct tevent_req);
1316         struct dcerpc_bind_state *state =
1317                 tevent_req_data(req,
1318                 struct dcerpc_bind_state);
1319         struct dcecli_connection *conn = state->p->conn;
1320         struct dcecli_security *sec = &conn->security_state;
1321         struct dcerpc_binding *b = NULL;
1322         NTSTATUS status;
1323         uint32_t flags;
1324
1325         /*
1326          * Note that pkt is allocated under raw_packet->data,
1327          * while raw_packet->data is a child of subreq.
1328          */
1329         talloc_steal(state, raw_packet->data);
1330         TALLOC_FREE(subreq);
1331
1332         /*
1333          * We trigger the callback in the next event run
1334          * because the code in this file might trigger
1335          * multiple request callbacks from within a single
1336          * while loop.
1337          *
1338          * In order to avoid segfaults from within
1339          * dcerpc_connection_dead() we call
1340          * tevent_req_defer_callback().
1341          */
1342         tevent_req_defer_callback(req, state->ev);
1343
1344         if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1345                 status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1346
1347                 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1348                          pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1349
1350                 tevent_req_nterror(req, status);
1351                 return;
1352         }
1353
1354         status = dcerpc_verify_ncacn_packet_header(pkt,
1355                                         DCERPC_PKT_BIND_ACK,
1356                                         pkt->u.bind_ack.auth_info.length,
1357                                         DCERPC_PFC_FLAG_FIRST |
1358                                         DCERPC_PFC_FLAG_LAST,
1359                                         DCERPC_PFC_FLAG_CONC_MPX |
1360                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
1361         if (!NT_STATUS_IS_OK(status)) {
1362                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1363                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1364                 return;
1365         }
1366
1367         if (pkt->u.bind_ack.num_results != 1) {
1368                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1369                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1370                 return;
1371         }
1372
1373         if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1374                 status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1375                 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1376                          pkt->u.bind_ack.ctx_list[0].reason.value,
1377                          nt_errstr(status)));
1378                 tevent_req_nterror(req, status);
1379                 return;
1380         }
1381
1382         /*
1383          * DCE-RPC 1.1 (c706) specifies
1384          * CONST_MUST_RCV_FRAG_SIZE as 1432
1385          */
1386         if (pkt->u.bind_ack.max_xmit_frag < 1432) {
1387                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1388                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1389                 return;
1390         }
1391         if (pkt->u.bind_ack.max_recv_frag < 1432) {
1392                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1393                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1394                 return;
1395         }
1396         conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1397                                       pkt->u.bind_ack.max_xmit_frag);
1398         conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1399                                       pkt->u.bind_ack.max_recv_frag);
1400
1401         flags = dcerpc_binding_get_flags(state->p->binding);
1402
1403         if ((flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1404             (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1405                 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1406         }
1407
1408         if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1409             (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1410                 conn->flags |= DCERPC_HEADER_SIGNING;
1411         }
1412
1413         /* the bind_ack might contain a reply set of credentials */
1414         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1415                 uint32_t auth_length;
1416
1417                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1418                                                   &pkt->u.bind_ack.auth_info,
1419                                                   sec->tmp_auth_info.in,
1420                                                   &auth_length, true);
1421                 if (tevent_req_nterror(req, status)) {
1422                         return;
1423                 }
1424         }
1425
1426         /*
1427          * We're the owner of the binding, so we're allowed to modify it.
1428          */
1429         b = discard_const_p(struct dcerpc_binding, state->p->binding);
1430         status = dcerpc_binding_set_assoc_group_id(b,
1431                                                    pkt->u.bind_ack.assoc_group_id);
1432         if (tevent_req_nterror(req, status)) {
1433                 return;
1434         }
1435
1436         tevent_req_done(req);
1437 }
1438
1439 NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1440 {
1441         return tevent_req_simple_recv_ntstatus(req);
1442 }
1443
1444 /* 
1445    perform a continued bind (and auth3)
1446 */
1447 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1448                       TALLOC_CTX *mem_ctx)
1449 {
1450         struct ncacn_packet pkt;
1451         NTSTATUS status;
1452         DATA_BLOB blob;
1453         uint32_t flags;
1454
1455         flags = dcerpc_binding_get_flags(p->binding);
1456
1457         init_ncacn_hdr(p->conn, &pkt);
1458
1459         pkt.ptype = DCERPC_PKT_AUTH3;
1460         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1461         pkt.call_id = next_call_id(p->conn);
1462         pkt.auth_length = 0;
1463         pkt.u.auth3.auth_info = data_blob(NULL, 0);
1464
1465         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1466                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1467         }
1468
1469         /* construct the NDR form of the packet */
1470         status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1471                                  p->conn->security_state.tmp_auth_info.out);
1472         if (!NT_STATUS_IS_OK(status)) {
1473                 return status;
1474         }
1475
1476         /* send it on its way */
1477         status = dcerpc_send_request(p->conn, &blob, false);
1478         if (!NT_STATUS_IS_OK(status)) {
1479                 return status;
1480         }
1481
1482         return NT_STATUS_OK;    
1483 }
1484
1485
1486 /*
1487   process a fragment received from the transport layer during a
1488   request
1489
1490   This function frees the data 
1491 */
1492 static void dcerpc_request_recv_data(struct dcecli_connection *c, 
1493                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1494 {
1495         struct rpc_request *req;
1496         unsigned int length;
1497         NTSTATUS status = NT_STATUS_OK;
1498
1499         /*
1500           if this is an authenticated connection then parse and check
1501           the auth info. We have to do this before finding the
1502           matching packet, as the request structure might have been
1503           removed due to a timeout, but if it has been we still need
1504           to run the auth routines so that we don't get the sign/seal
1505           info out of step with the server
1506         */
1507         if (pkt->ptype == DCERPC_PKT_RESPONSE) {
1508                 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1509         }
1510
1511         /* find the matching request */
1512         for (req=c->pending;req;req=req->next) {
1513                 if (pkt->call_id == req->call_id) break;
1514         }
1515
1516 #if 0
1517         /* useful for testing certain vendors RPC servers */
1518         if (req == NULL && c->pending && pkt->call_id == 0) {
1519                 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1520                 req = c->pending;
1521         }
1522 #endif
1523
1524         if (req == NULL) {
1525                 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1526                 data_blob_free(raw_packet);
1527                 return;
1528         }
1529
1530         talloc_steal(req, raw_packet->data);
1531
1532         if (req->recv_handler != NULL) {
1533                 dcerpc_req_dequeue(req);
1534                 req->state = RPC_REQUEST_DONE;
1535
1536                 /*
1537                  * We have to look at shipping further requests before calling
1538                  * the async function, that one might close the pipe
1539                  */
1540                 dcerpc_schedule_io_trigger(c);
1541
1542                 req->recv_handler(req, raw_packet, pkt);
1543                 return;
1544         }
1545
1546         if (pkt->ptype == DCERPC_PKT_FAULT) {
1547                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1548                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1549                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1550                         dcerpc_connection_dead(c, status);
1551                         return;
1552                 }
1553                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1554                         dcerpc_connection_dead(c, status);
1555                         return;
1556                 }
1557                 req->fault_code = pkt->u.fault.status;
1558                 req->status = NT_STATUS_NET_WRITE_FAULT;
1559                 goto req_done;
1560         }
1561
1562         if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1563                 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1564                          (int)pkt->ptype)); 
1565                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1566                 return;
1567         }
1568
1569         /* now check the status from the auth routines, and if it failed then fail
1570            this request accordingly */
1571         if (!NT_STATUS_IS_OK(status)) {
1572                 dcerpc_connection_dead(c, status);
1573                 return;
1574         }
1575
1576         length = pkt->u.response.stub_and_verifier.length;
1577
1578         if (req->payload.length + length > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
1579                 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1580                          (unsigned)req->payload.length + length,
1581                          DCERPC_NCACN_PAYLOAD_MAX_SIZE));
1582                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1583                 return;
1584         }
1585
1586         if (length > 0) {
1587                 req->payload.data = talloc_realloc(req, 
1588                                                    req->payload.data, 
1589                                                    uint8_t,
1590                                                    req->payload.length + length);
1591                 if (!req->payload.data) {
1592                         req->status = NT_STATUS_NO_MEMORY;
1593                         goto req_done;
1594                 }
1595                 memcpy(req->payload.data+req->payload.length, 
1596                        pkt->u.response.stub_and_verifier.data, length);
1597                 req->payload.length += length;
1598         }
1599
1600         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1601                 data_blob_free(raw_packet);
1602                 dcerpc_send_read(c);
1603                 return;
1604         }
1605
1606         if (req->verify_bitmask1) {
1607                 req->p->conn->security_state.verified_bitmask1 = true;
1608         }
1609         if (req->verify_pcontext) {
1610                 req->p->verified_pcontext = true;
1611         }
1612
1613         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1614                 req->flags |= DCERPC_PULL_BIGENDIAN;
1615         } else {
1616                 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1617         }
1618
1619 req_done:
1620         data_blob_free(raw_packet);
1621
1622         /* we've got the full payload */
1623         dcerpc_req_dequeue(req);
1624         req->state = RPC_REQUEST_DONE;
1625
1626         /*
1627          * We have to look at shipping further requests before calling
1628          * the async function, that one might close the pipe
1629          */
1630         dcerpc_schedule_io_trigger(c);
1631
1632         if (req->async.callback) {
1633                 req->async.callback(req);
1634         }
1635 }
1636
1637 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
1638
1639 /*
1640   perform the send side of a async dcerpc request
1641 */
1642 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
1643                                                struct dcerpc_pipe *p,
1644                                                const struct GUID *object,
1645                                                uint16_t opnum,
1646                                                DATA_BLOB *stub_data)
1647 {
1648         struct rpc_request *req;
1649         NTSTATUS status;
1650
1651         req = talloc_zero(mem_ctx, struct rpc_request);
1652         if (req == NULL) {
1653                 return NULL;
1654         }
1655
1656         req->p = p;
1657         req->call_id = next_call_id(p->conn);
1658         req->state = RPC_REQUEST_QUEUED;
1659
1660         if (object != NULL) {
1661                 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1662                 if (req->object == NULL) {
1663                         talloc_free(req);
1664                         return NULL;
1665                 }
1666         }
1667
1668         req->opnum = opnum;
1669         req->request_data.length = stub_data->length;
1670         req->request_data.data = stub_data->data;
1671
1672         status = dcerpc_request_prepare_vt(req);
1673         if (!NT_STATUS_IS_OK(status)) {
1674                 talloc_free(req);
1675                 return NULL;
1676         }
1677
1678         DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1679         talloc_set_destructor(req, dcerpc_req_dequeue);
1680
1681         dcerpc_schedule_io_trigger(p->conn);
1682
1683         if (p->request_timeout) {
1684                 tevent_add_timer(p->conn->event_ctx, req,
1685                                 timeval_current_ofs(p->request_timeout, 0), 
1686                                 dcerpc_timeout_handler, req);
1687         }
1688
1689         return req;
1690 }
1691
1692 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1693 {
1694         struct dcecli_security *sec = &req->p->conn->security_state;
1695         struct dcerpc_sec_verification_trailer *t;
1696         struct dcerpc_sec_vt *c = NULL;
1697         struct ndr_push *ndr = NULL;
1698         enum ndr_err_code ndr_err;
1699
1700         if (sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1701                 return NT_STATUS_OK;
1702         }
1703
1704         t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1705         if (t == NULL) {
1706                 return NT_STATUS_NO_MEMORY;
1707         }
1708
1709         if (!sec->verified_bitmask1) {
1710                 t->commands = talloc_realloc(t, t->commands,
1711                                              struct dcerpc_sec_vt,
1712                                              t->count.count + 1);
1713                 if (t->commands == NULL) {
1714                         return NT_STATUS_NO_MEMORY;
1715                 }
1716                 c = &t->commands[t->count.count++];
1717                 ZERO_STRUCTP(c);
1718
1719                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1720                 if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1721                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1722                 }
1723                 req->verify_bitmask1 = true;
1724         }
1725
1726         if (!req->p->verified_pcontext) {
1727                 t->commands = talloc_realloc(t, t->commands,
1728                                              struct dcerpc_sec_vt,
1729                                              t->count.count + 1);
1730                 if (t->commands == NULL) {
1731                         return NT_STATUS_NO_MEMORY;
1732                 }
1733                 c = &t->commands[t->count.count++];
1734                 ZERO_STRUCTP(c);
1735
1736                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1737                 c->u.pcontext.abstract_syntax = req->p->syntax;
1738                 c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1739
1740                 req->verify_pcontext = true;
1741         }
1742
1743         if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1744                 t->commands = talloc_realloc(t, t->commands,
1745                                              struct dcerpc_sec_vt,
1746                                              t->count.count + 1);
1747                 if (t->commands == NULL) {
1748                         return NT_STATUS_NO_MEMORY;
1749                 }
1750                 c = &t->commands[t->count.count++];
1751                 ZERO_STRUCTP(c);
1752
1753                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1754                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1755                 if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1756                         c->u.header2.drep[0] = 0;
1757                 } else {
1758                         c->u.header2.drep[0] = DCERPC_DREP_LE;
1759                 }
1760                 c->u.header2.drep[1] = 0;
1761                 c->u.header2.drep[2] = 0;
1762                 c->u.header2.drep[3] = 0;
1763                 c->u.header2.call_id = req->call_id;
1764                 c->u.header2.context_id = req->p->context_id;
1765                 c->u.header2.opnum = req->opnum;
1766         }
1767
1768         if (t->count.count == 0) {
1769                 TALLOC_FREE(t);
1770                 return NT_STATUS_OK;
1771         }
1772
1773         c = &t->commands[t->count.count - 1];
1774         c->command |= DCERPC_SEC_VT_COMMAND_END;
1775
1776         if (DEBUGLEVEL >= 10) {
1777                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1778         }
1779
1780         ndr = ndr_push_init_ctx(req);
1781         if (ndr == NULL) {
1782                 return NT_STATUS_NO_MEMORY;
1783         }
1784
1785         /*
1786          * for now we just copy and append
1787          */
1788
1789         ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1790                                  req->request_data.length);
1791         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1792                 return ndr_map_error2ntstatus(ndr_err);
1793         }
1794
1795         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1796                                                 NDR_SCALARS | NDR_BUFFERS,
1797                                                 t);
1798         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1799                 return ndr_map_error2ntstatus(ndr_err);
1800         }
1801         req->request_data = ndr_push_blob(ndr);
1802
1803         return NT_STATUS_OK;
1804 }
1805
1806 /*
1807   Send a request using the transport
1808 */
1809
1810 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1811 {
1812         struct rpc_request *req;
1813         struct dcerpc_pipe *p;
1814         DATA_BLOB *stub_data;
1815         struct ncacn_packet pkt;
1816         DATA_BLOB blob;
1817         uint32_t remaining, chunk_size;
1818         bool first_packet = true;
1819         size_t sig_size = 0;
1820         bool need_async = false;
1821         bool can_async = true;
1822
1823         req = c->request_queue;
1824         if (req == NULL) {
1825                 return;
1826         }
1827
1828         p = req->p;
1829         stub_data = &req->request_data;
1830
1831         if (c->pending) {
1832                 need_async = true;
1833         }
1834
1835         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1836                 can_async = gensec_have_feature(c->security_state.generic_state,
1837                                                 GENSEC_FEATURE_ASYNC_REPLIES);
1838         }
1839
1840         if (need_async && !can_async) {
1841                 req->wait_for_sync = true;
1842                 return;
1843         }
1844
1845         DLIST_REMOVE(c->request_queue, req);
1846         DLIST_ADD(c->pending, req);
1847         req->state = RPC_REQUEST_PENDING;
1848
1849         init_ncacn_hdr(p->conn, &pkt);
1850
1851         remaining = stub_data->length;
1852
1853         /* we can write a full max_recv_frag size, minus the dcerpc
1854            request header size */
1855         chunk_size = p->conn->srv_max_recv_frag;
1856         chunk_size -= DCERPC_REQUEST_LENGTH;
1857         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1858                 size_t max_payload = chunk_size;
1859
1860                 max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1861                 max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1862
1863                 sig_size = gensec_sig_size(c->security_state.generic_state,
1864                                            max_payload);
1865                 if (sig_size) {
1866                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1867                         chunk_size -= sig_size;
1868                 }
1869         }
1870         chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1871
1872         pkt.ptype = DCERPC_PKT_REQUEST;
1873         pkt.call_id = req->call_id;
1874         pkt.auth_length = 0;
1875         pkt.pfc_flags = 0;
1876         pkt.u.request.context_id = p->context_id;
1877         pkt.u.request.opnum = req->opnum;
1878
1879         if (req->object) {
1880                 pkt.u.request.object.object = *req->object;
1881                 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1882                 chunk_size -= ndr_size_GUID(req->object,0);
1883         }
1884
1885         /* we send a series of pdus without waiting for a reply */
1886         while (remaining > 0 || first_packet) {
1887                 uint32_t chunk = MIN(chunk_size, remaining);
1888                 bool last_frag = false;
1889                 bool do_trans = false;
1890
1891                 first_packet = false;
1892                 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1893
1894                 if (remaining == stub_data->length) {
1895                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1896                 }
1897                 if (chunk == remaining) {
1898                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1899                         last_frag = true;
1900                 }
1901
1902                 pkt.u.request.alloc_hint = remaining;
1903                 pkt.u.request.stub_and_verifier.data = stub_data->data + 
1904                         (stub_data->length - remaining);
1905                 pkt.u.request.stub_and_verifier.length = chunk;
1906
1907                 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1908                 if (!NT_STATUS_IS_OK(req->status)) {
1909                         req->state = RPC_REQUEST_DONE;
1910                         DLIST_REMOVE(p->conn->pending, req);
1911                         return;
1912                 }
1913
1914                 if (last_frag && !need_async) {
1915                         do_trans = true;
1916                 }
1917
1918                 req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1919                 if (!NT_STATUS_IS_OK(req->status)) {
1920                         req->state = RPC_REQUEST_DONE;
1921                         DLIST_REMOVE(p->conn->pending, req);
1922                         return;
1923                 }               
1924
1925                 if (last_frag && !do_trans) {
1926                         req->status = dcerpc_send_read(p->conn);
1927                         if (!NT_STATUS_IS_OK(req->status)) {
1928                                 req->state = RPC_REQUEST_DONE;
1929                                 DLIST_REMOVE(p->conn->pending, req);
1930                                 return;
1931                         }
1932                 }
1933
1934                 remaining -= chunk;
1935         }
1936 }
1937
1938 static void dcerpc_io_trigger(struct tevent_context *ctx,
1939                               struct tevent_immediate *im,
1940                               void *private_data)
1941 {
1942         struct dcecli_connection *c =
1943                 talloc_get_type_abort(private_data,
1944                 struct dcecli_connection);
1945
1946         c->io_trigger_pending = false;
1947
1948         dcerpc_schedule_io_trigger(c);
1949
1950         dcerpc_ship_next_request(c);
1951 }
1952
1953 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1954 {
1955         if (c->dead) {
1956                 return;
1957         }
1958
1959         if (c->request_queue == NULL) {
1960                 return;
1961         }
1962
1963         if (c->request_queue->wait_for_sync && c->pending) {
1964                 return;
1965         }
1966
1967         if (c->io_trigger_pending) {
1968                 return;
1969         }
1970
1971         c->io_trigger_pending = true;
1972
1973         tevent_schedule_immediate(c->io_trigger,
1974                                   c->event_ctx,
1975                                   dcerpc_io_trigger,
1976                                   c);
1977 }
1978
1979 /*
1980   perform the receive side of a async dcerpc request
1981 */
1982 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1983                                     TALLOC_CTX *mem_ctx,
1984                                     DATA_BLOB *stub_data)
1985 {
1986         NTSTATUS status;
1987
1988         while (req->state != RPC_REQUEST_DONE) {
1989                 struct tevent_context *ctx = req->p->conn->event_ctx;
1990                 if (tevent_loop_once(ctx) != 0) {
1991                         return NT_STATUS_CONNECTION_DISCONNECTED;
1992                 }
1993         }
1994         *stub_data = req->payload;
1995         status = req->status;
1996         if (stub_data->data) {
1997                 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1998         }
1999         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
2000                 req->p->last_fault_code = req->fault_code;
2001         }
2002         talloc_unlink(talloc_parent(req), req);
2003         return status;
2004 }
2005
2006 /*
2007   this is a paranoid NDR validator. For every packet we push onto the wire
2008   we pull it back again, then push it again. Then we compare the raw NDR data
2009   for that to the NDR we initially generated. If they don't match then we know
2010   we must have a bug in either the pull or push side of our code
2011 */
2012 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 
2013                                        TALLOC_CTX *mem_ctx,
2014                                        DATA_BLOB blob,
2015                                        size_t struct_size,
2016                                        ndr_push_flags_fn_t ndr_push,
2017                                        ndr_pull_flags_fn_t ndr_pull)
2018 {
2019         void *st;
2020         struct ndr_pull *pull;
2021         struct ndr_push *push;
2022         DATA_BLOB blob2;
2023         enum ndr_err_code ndr_err;
2024
2025         st = talloc_size(mem_ctx, struct_size);
2026         if (!st) {
2027                 return NT_STATUS_NO_MEMORY;
2028         }
2029
2030         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2031         if (!pull) {
2032                 return NT_STATUS_NO_MEMORY;
2033         }
2034         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2035
2036         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2037                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
2038         }
2039
2040         if (c->flags & DCERPC_NDR64) {
2041                 pull->flags |= LIBNDR_FLAG_NDR64;
2042         }
2043
2044         ndr_err = ndr_pull(pull, NDR_IN, st);
2045         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2046                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2047                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2048                                          "failed input validation pull - %s",
2049                                          nt_errstr(status));
2050                 return ndr_map_error2ntstatus(ndr_err);
2051         }
2052
2053         push = ndr_push_init_ctx(mem_ctx);
2054         if (!push) {
2055                 return NT_STATUS_NO_MEMORY;
2056         }       
2057
2058         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2059                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
2060         }
2061
2062         if (c->flags & DCERPC_NDR64) {
2063                 push->flags |= LIBNDR_FLAG_NDR64;
2064         }
2065
2066         ndr_err = ndr_push(push, NDR_IN, st);
2067         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2068                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2069                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2070                                          "failed input validation push - %s",
2071                                          nt_errstr(status));
2072                 return ndr_map_error2ntstatus(ndr_err);
2073         }
2074
2075         blob2 = ndr_push_blob(push);
2076
2077         if (data_blob_cmp(&blob, &blob2) != 0) {
2078                 DEBUG(3,("original:\n"));
2079                 dump_data(3, blob.data, blob.length);
2080                 DEBUG(3,("secondary:\n"));
2081                 dump_data(3, blob2.data, blob2.length);
2082                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2083                                          "failed input validation blobs doesn't match");
2084                 return ndr_map_error2ntstatus(ndr_err);
2085         }
2086
2087         return NT_STATUS_OK;
2088 }
2089
2090 /*
2091   this is a paranoid NDR input validator. For every packet we pull
2092   from the wire we push it back again then pull and push it
2093   again. Then we compare the raw NDR data for that to the NDR we
2094   initially generated. If they don't match then we know we must have a
2095   bug in either the pull or push side of our code
2096 */
2097 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
2098                                         struct ndr_pull *pull_in,
2099                                         void *struct_ptr,
2100                                         size_t struct_size,
2101                                         ndr_push_flags_fn_t ndr_push,
2102                                         ndr_pull_flags_fn_t ndr_pull,
2103                                         ndr_print_function_t ndr_print)
2104 {
2105         void *st;
2106         struct ndr_pull *pull;
2107         struct ndr_push *push;
2108         DATA_BLOB blob, blob2;
2109         TALLOC_CTX *mem_ctx = pull_in;
2110         char *s1, *s2;
2111         enum ndr_err_code ndr_err;
2112
2113         st = talloc_size(mem_ctx, struct_size);
2114         if (!st) {
2115                 return NT_STATUS_NO_MEMORY;
2116         }
2117         memcpy(st, struct_ptr, struct_size);
2118
2119         push = ndr_push_init_ctx(mem_ctx);
2120         if (!push) {
2121                 return NT_STATUS_NO_MEMORY;
2122         }       
2123
2124         ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
2125         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2126                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2127                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2128                                          "failed output validation push - %s",
2129                                          nt_errstr(status));
2130                 return ndr_map_error2ntstatus(ndr_err);
2131         }
2132
2133         blob = ndr_push_blob(push);
2134
2135         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2136         if (!pull) {
2137                 return NT_STATUS_NO_MEMORY;
2138         }
2139
2140         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2141         ndr_err = ndr_pull(pull, NDR_OUT, st);
2142         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2143                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2144                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2145                                          "failed output validation pull - %s",
2146                                          nt_errstr(status));
2147                 return ndr_map_error2ntstatus(ndr_err);
2148         }
2149
2150         push = ndr_push_init_ctx(mem_ctx);
2151         if (!push) {
2152                 return NT_STATUS_NO_MEMORY;
2153         }       
2154
2155         ndr_err = ndr_push(push, NDR_OUT, st);
2156         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2157                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2158                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2159                                          "failed output validation push2 - %s",
2160                                          nt_errstr(status));
2161                 return ndr_map_error2ntstatus(ndr_err);
2162         }
2163
2164         blob2 = ndr_push_blob(push);
2165
2166         if (data_blob_cmp(&blob, &blob2) != 0) {
2167                 DEBUG(3,("original:\n"));
2168                 dump_data(3, blob.data, blob.length);
2169                 DEBUG(3,("secondary:\n"));
2170                 dump_data(3, blob2.data, blob2.length);
2171                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2172                                          "failed output validation blobs doesn't match");
2173                 return ndr_map_error2ntstatus(ndr_err);
2174         }
2175
2176         /* this checks the printed forms of the two structures, which effectively
2177            tests all of the value() attributes */
2178         s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
2179                                        NDR_OUT, struct_ptr);
2180         s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
2181                                        NDR_OUT, st);
2182         if (strcmp(s1, s2) != 0) {
2183 #if 1
2184                 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
2185 #else
2186                 /* this is sometimes useful */
2187                 printf("VALIDATE ERROR\n");
2188                 file_save("wire.dat", s1, strlen(s1));
2189                 file_save("gen.dat", s2, strlen(s2));
2190                 system("diff -u wire.dat gen.dat");
2191 #endif
2192                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2193                                          "failed output validation strings doesn't match");
2194                 return ndr_map_error2ntstatus(ndr_err);
2195         }
2196
2197         return NT_STATUS_OK;
2198 }
2199
2200 /*
2201   a useful function for retrieving the server name we connected to
2202 */
2203 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2204 {
2205         return p->conn ? p->conn->server_name : NULL;
2206 }
2207
2208
2209 /*
2210   get the dcerpc auth_level for a open connection
2211 */
2212 uint32_t dcerpc_auth_level(struct dcecli_connection *c) 
2213 {
2214         uint8_t auth_level;
2215
2216         if (c->flags & DCERPC_SEAL) {
2217                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2218         } else if (c->flags & DCERPC_SIGN) {
2219                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2220         } else if (c->flags & DCERPC_CONNECT) {
2221                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2222         } else {
2223                 auth_level = DCERPC_AUTH_LEVEL_NONE;
2224         }
2225         return auth_level;
2226 }
2227
2228 struct dcerpc_alter_context_state {
2229         struct tevent_context *ev;
2230         struct dcerpc_pipe *p;
2231 };
2232
2233 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
2234 static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
2235                                               DATA_BLOB *raw_packet,
2236                                               struct ncacn_packet *pkt);
2237
2238 struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
2239                                              struct tevent_context *ev,
2240                                              struct dcerpc_pipe *p,
2241                                              const struct ndr_syntax_id *syntax,
2242                                              const struct ndr_syntax_id *transfer_syntax)
2243 {
2244         struct tevent_req *req;
2245         struct dcerpc_alter_context_state *state;
2246         struct ncacn_packet pkt;
2247         DATA_BLOB blob;
2248         NTSTATUS status;
2249         struct rpc_request *subreq;
2250         uint32_t flags;
2251
2252         req = tevent_req_create(mem_ctx, &state,
2253                                 struct dcerpc_alter_context_state);
2254         if (req == NULL) {
2255                 return NULL;
2256         }
2257
2258         state->ev = ev;
2259         state->p = p;
2260
2261         p->syntax = *syntax;
2262         p->transfer_syntax = *transfer_syntax;
2263
2264         flags = dcerpc_binding_get_flags(p->binding);
2265
2266         init_ncacn_hdr(p->conn, &pkt);
2267
2268         pkt.ptype = DCERPC_PKT_ALTER;
2269         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2270         pkt.call_id = p->conn->call_id;
2271         pkt.auth_length = 0;
2272
2273         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2274                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2275         }
2276
2277         pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2278         pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2279         pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2280         pkt.u.alter.num_contexts = 1;
2281         pkt.u.alter.ctx_list = talloc_array(state, struct dcerpc_ctx_list, 1);
2282         if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2283                 return tevent_req_post(req, ev);
2284         }
2285         pkt.u.alter.ctx_list[0].context_id = p->context_id;
2286         pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2287         pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2288         pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2289         pkt.u.alter.auth_info = data_blob(NULL, 0);
2290
2291         /* construct the NDR form of the packet */
2292         status = ncacn_push_auth(&blob, state, &pkt,
2293                                  p->conn->security_state.tmp_auth_info.out);
2294         if (tevent_req_nterror(req, status)) {
2295                 return tevent_req_post(req, ev);
2296         }
2297
2298         /*
2299          * we allocate a dcerpc_request so we can be in the same
2300          * request queue as normal requests
2301          */
2302         subreq = talloc_zero(state, struct rpc_request);
2303         if (tevent_req_nomem(subreq, req)) {
2304                 return tevent_req_post(req, ev);
2305         }
2306
2307         subreq->state = RPC_REQUEST_PENDING;
2308         subreq->call_id = pkt.call_id;
2309         subreq->async.private_data = req;
2310         subreq->async.callback = dcerpc_alter_context_fail_handler;
2311         subreq->p = p;
2312         subreq->recv_handler = dcerpc_alter_context_recv_handler;
2313         DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
2314         talloc_set_destructor(subreq, dcerpc_req_dequeue);
2315
2316         status = dcerpc_send_request(p->conn, &blob, true);
2317         if (tevent_req_nterror(req, status)) {
2318                 return tevent_req_post(req, ev);
2319         }
2320
2321         tevent_add_timer(ev, subreq,
2322                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2323                          dcerpc_timeout_handler, subreq);
2324
2325         return req;
2326 }
2327
2328 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
2329 {
2330         struct tevent_req *req =
2331                 talloc_get_type_abort(subreq->async.private_data,
2332                 struct tevent_req);
2333         struct dcerpc_alter_context_state *state =
2334                 tevent_req_data(req,
2335                 struct dcerpc_alter_context_state);
2336         NTSTATUS status = subreq->status;
2337
2338         TALLOC_FREE(subreq);
2339
2340         /*
2341          * We trigger the callback in the next event run
2342          * because the code in this file might trigger
2343          * multiple request callbacks from within a single
2344          * while loop.
2345          *
2346          * In order to avoid segfaults from within
2347          * dcerpc_connection_dead() we call
2348          * tevent_req_defer_callback().
2349          */
2350         tevent_req_defer_callback(req, state->ev);
2351
2352         tevent_req_nterror(req, status);
2353 }
2354
2355 static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2356                                               DATA_BLOB *raw_packet,
2357                                               struct ncacn_packet *pkt)
2358 {
2359         struct tevent_req *req =
2360                 talloc_get_type_abort(subreq->async.private_data,
2361                 struct tevent_req);
2362         struct dcerpc_alter_context_state *state =
2363                 tevent_req_data(req,
2364                 struct dcerpc_alter_context_state);
2365         struct dcecli_connection *conn = state->p->conn;
2366         struct dcecli_security *sec = &conn->security_state;
2367         NTSTATUS status;
2368
2369         /*
2370          * Note that pkt is allocated under raw_packet->data,
2371          * while raw_packet->data is a child of subreq.
2372          */
2373         talloc_steal(state, raw_packet->data);
2374         TALLOC_FREE(subreq);
2375
2376         /*
2377          * We trigger the callback in the next event run
2378          * because the code in this file might trigger
2379          * multiple request callbacks from within a single
2380          * while loop.
2381          *
2382          * In order to avoid segfaults from within
2383          * dcerpc_connection_dead() we call
2384          * tevent_req_defer_callback().
2385          */
2386         tevent_req_defer_callback(req, state->ev);
2387
2388         if (pkt->ptype == DCERPC_PKT_FAULT) {
2389                 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2390                          dcerpc_errstr(state, pkt->u.fault.status)));
2391                 if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
2392                         state->p->last_fault_code = pkt->u.fault.status;
2393                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2394                 } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
2395                         state->p->last_fault_code = pkt->u.fault.status;
2396                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2397                 } else {
2398                         state->p->last_fault_code = pkt->u.fault.status;
2399                         status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2400                         tevent_req_nterror(req, status);
2401                 }
2402                 return;
2403         }
2404
2405         status = dcerpc_verify_ncacn_packet_header(pkt,
2406                                         DCERPC_PKT_ALTER_RESP,
2407                                         pkt->u.alter_resp.auth_info.length,
2408                                         DCERPC_PFC_FLAG_FIRST |
2409                                         DCERPC_PFC_FLAG_LAST,
2410                                         DCERPC_PFC_FLAG_CONC_MPX |
2411                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
2412         if (!NT_STATUS_IS_OK(status)) {
2413                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2414                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2415                 return;
2416         }
2417
2418         if (pkt->u.alter_resp.num_results != 1) {
2419                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2420                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2421                 return;
2422         }
2423
2424         if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2425                 status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2426                 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2427                          pkt->u.alter_resp.ctx_list[0].reason.value,
2428                          nt_errstr(status)));
2429                 tevent_req_nterror(req, status);
2430                 return;
2431         }
2432
2433         /* the alter_resp might contain a reply set of credentials */
2434         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2435                 uint32_t auth_length;
2436
2437                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2438                                                   &pkt->u.alter_resp.auth_info,
2439                                                   sec->tmp_auth_info.in,
2440                                                   &auth_length, true);
2441                 if (tevent_req_nterror(req, status)) {
2442                         return;
2443                 }
2444         }
2445
2446         tevent_req_done(req);
2447 }
2448
2449 NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2450 {
2451         return tevent_req_simple_recv_ntstatus(req);
2452 }
2453
2454 /* 
2455    send a dcerpc alter_context request
2456 */
2457 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 
2458                               TALLOC_CTX *mem_ctx,
2459                               const struct ndr_syntax_id *syntax,
2460                               const struct ndr_syntax_id *transfer_syntax)
2461 {
2462         struct tevent_req *subreq;
2463         struct tevent_context *ev = p->conn->event_ctx;
2464         bool ok;
2465
2466         /* TODO: create a new event context here */
2467
2468         subreq = dcerpc_alter_context_send(mem_ctx, ev,
2469                                            p, syntax, transfer_syntax);
2470         if (subreq == NULL) {
2471                 return NT_STATUS_NO_MEMORY;
2472         }
2473
2474         ok = tevent_req_poll(subreq, ev);
2475         if (!ok) {
2476                 NTSTATUS status;
2477                 status = map_nt_error_from_unix_common(errno);
2478                 return status;
2479         }
2480
2481         return dcerpc_alter_context_recv(subreq);
2482 }
2483
2484 static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2485 {
2486         if (c->transport.stream == NULL) {
2487                 return;
2488         }
2489
2490         tevent_queue_stop(c->transport.write_queue);
2491         TALLOC_FREE(c->transport.read_subreq);
2492         TALLOC_FREE(c->transport.stream);
2493
2494         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2495                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2496         }
2497
2498         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2499                 status = NT_STATUS_END_OF_FILE;
2500         }
2501
2502         dcerpc_recv_data(c, NULL, status);
2503 }
2504
2505
2506 /*
2507    shutdown SMB pipe connection
2508 */
2509 struct dcerpc_shutdown_pipe_state {
2510         struct dcecli_connection *c;
2511         NTSTATUS status;
2512 };
2513
2514 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
2515
2516 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2517 {
2518         struct dcerpc_shutdown_pipe_state *state;
2519         struct tevent_req *subreq;
2520
2521         if (c->transport.stream == NULL) {
2522                 return NT_STATUS_OK;
2523         }
2524
2525         state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2526         if (state == NULL) {
2527                 return NT_STATUS_NO_MEMORY;
2528         }
2529         state->c = c;
2530         state->status = status;
2531
2532         subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2533         if (subreq == NULL) {
2534                 return NT_STATUS_NO_MEMORY;
2535         }
2536         tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2537
2538         return status;
2539 }
2540
2541 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
2542 {
2543         struct dcerpc_shutdown_pipe_state *state =
2544                 tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
2545         struct dcecli_connection *c = state->c;
2546         NTSTATUS status = state->status;
2547         int error;
2548
2549         /*
2550          * here we ignore the return values...
2551          */
2552         tstream_disconnect_recv(subreq, &error);
2553         TALLOC_FREE(subreq);
2554
2555         TALLOC_FREE(state);
2556
2557         dcerpc_transport_dead(c, status);
2558 }
2559
2560
2561
2562 struct dcerpc_send_read_state {
2563         struct dcecli_connection *p;
2564 };
2565
2566 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2567 {
2568         struct dcecli_connection *p = state->p;
2569
2570         p->transport.read_subreq = NULL;
2571
2572         return 0;
2573 }
2574
2575 static void dcerpc_send_read_done(struct tevent_req *subreq);
2576
2577 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2578 {
2579         struct dcerpc_send_read_state *state;
2580
2581         if (p->transport.read_subreq != NULL) {
2582                 p->transport.pending_reads++;
2583                 return NT_STATUS_OK;
2584         }
2585
2586         state = talloc_zero(p, struct dcerpc_send_read_state);
2587         if (state == NULL) {
2588                 return NT_STATUS_NO_MEMORY;
2589         }
2590         state->p = p;
2591
2592         talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2593
2594         p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2595                                                           p->event_ctx,
2596                                                           p->transport.stream);
2597         if (p->transport.read_subreq == NULL) {
2598                 return NT_STATUS_NO_MEMORY;
2599         }
2600         tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2601
2602         return NT_STATUS_OK;
2603 }
2604
2605 static void dcerpc_send_read_done(struct tevent_req *subreq)
2606 {
2607         struct dcerpc_send_read_state *state =
2608                 tevent_req_callback_data(subreq,
2609                                          struct dcerpc_send_read_state);
2610         struct dcecli_connection *p = state->p;
2611         NTSTATUS status;
2612         struct ncacn_packet *pkt;
2613         DATA_BLOB blob;
2614
2615         status = dcerpc_read_ncacn_packet_recv(subreq, state,
2616                                                &pkt, &blob);
2617         TALLOC_FREE(subreq);
2618         if (!NT_STATUS_IS_OK(status)) {
2619                 TALLOC_FREE(state);
2620                 dcerpc_transport_dead(p, status);
2621                 return;
2622         }
2623
2624         /*
2625          * here we steal into thet connection context,
2626          * but p->transport.recv_data() will steal or free it again
2627          */
2628         talloc_steal(p, blob.data);
2629         TALLOC_FREE(state);
2630
2631         if (p->transport.pending_reads > 0) {
2632                 p->transport.pending_reads--;
2633
2634                 status = dcerpc_send_read(p);
2635                 if (!NT_STATUS_IS_OK(status)) {
2636                         dcerpc_transport_dead(p, status);
2637                         return;
2638                 }
2639         }
2640
2641         dcerpc_recv_data(p, &blob, NT_STATUS_OK);
2642 }
2643
2644 struct dcerpc_send_request_state {
2645         struct dcecli_connection *p;
2646         DATA_BLOB blob;
2647         struct iovec iov;
2648 };
2649
2650 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
2651 {
2652         struct dcecli_connection *p = state->p;
2653
2654         p->transport.read_subreq = NULL;
2655
2656         return 0;
2657 }
2658
2659 static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
2660 static void dcerpc_send_request_done(struct tevent_req *subreq);
2661
2662 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2663                                     bool trigger_read)
2664 {
2665         struct dcerpc_send_request_state *state;
2666         struct tevent_req *subreq;
2667         bool use_trans = trigger_read;
2668
2669         if (p->transport.stream == NULL) {
2670                 return NT_STATUS_CONNECTION_DISCONNECTED;
2671         }
2672
2673         state = talloc_zero(p, struct dcerpc_send_request_state);
2674         if (state == NULL) {
2675                 return NT_STATUS_NO_MEMORY;
2676         }
2677         state->p = p;
2678
2679         state->blob = data_blob_talloc(state, data->data, data->length);
2680         if (state->blob.data == NULL) {
2681                 TALLOC_FREE(state);
2682                 return NT_STATUS_NO_MEMORY;
2683         }
2684         state->iov.iov_base = (void *)state->blob.data;
2685         state->iov.iov_len = state->blob.length;
2686
2687         if (p->transport.read_subreq != NULL) {
2688                 use_trans = false;
2689         }
2690
2691         if (!tstream_is_smbXcli_np(p->transport.stream)) {
2692                 use_trans = false;
2693         }
2694
2695         if (use_trans) {
2696                 /*
2697                  * we need to block reads until our write is
2698                  * the next in the write queue.
2699                  */
2700                 p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2701                                                              p->transport.write_queue);
2702                 if (p->transport.read_subreq == NULL) {
2703                         TALLOC_FREE(state);
2704                         return NT_STATUS_NO_MEMORY;
2705                 }
2706                 tevent_req_set_callback(p->transport.read_subreq,
2707                                         dcerpc_send_request_wait_done,
2708                                         state);
2709
2710                 talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2711
2712                 trigger_read = false;
2713         }
2714
2715         subreq = tstream_writev_queue_send(state, p->event_ctx,
2716                                            p->transport.stream,
2717                                            p->transport.write_queue,
2718                                            &state->iov, 1);
2719         if (subreq == NULL) {
2720                 TALLOC_FREE(state);
2721                 return NT_STATUS_NO_MEMORY;
2722         }
2723         tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2724
2725         if (trigger_read) {
2726                 dcerpc_send_read(p);
2727         }
2728
2729         return NT_STATUS_OK;
2730 }
2731
2732 static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2733 {
2734         struct dcerpc_send_request_state *state =
2735                 tevent_req_callback_data(subreq,
2736                 struct dcerpc_send_request_state);
2737         struct dcecli_connection *p = state->p;
2738         NTSTATUS status;
2739         bool ok;
2740
2741         p->transport.read_subreq = NULL;
2742         talloc_set_destructor(state, NULL);
2743
2744         ok = tevent_queue_wait_recv(subreq);
2745         if (!ok) {
2746                 TALLOC_FREE(state);
2747                 dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2748                 return;
2749         }
2750
2751         if (tevent_queue_length(p->transport.write_queue) <= 2) {
2752                 status = tstream_smbXcli_np_use_trans(p->transport.stream);
2753                 if (!NT_STATUS_IS_OK(status)) {
2754                         TALLOC_FREE(state);
2755                         dcerpc_transport_dead(p, status);
2756                         return;
2757                 }
2758         }
2759
2760         /* we free subreq after tstream_cli_np_use_trans */
2761         TALLOC_FREE(subreq);
2762
2763         dcerpc_send_read(p);
2764 }
2765
2766 static void dcerpc_send_request_done(struct tevent_req *subreq)
2767 {
2768         struct dcerpc_send_request_state *state =
2769                 tevent_req_callback_data(subreq,
2770                 struct dcerpc_send_request_state);
2771         int ret;
2772         int error;
2773
2774         ret = tstream_writev_queue_recv(subreq, &error);
2775         TALLOC_FREE(subreq);
2776         if (ret == -1) {
2777                 struct dcecli_connection *p = state->p;
2778                 NTSTATUS status = map_nt_error_from_unix_common(error);
2779
2780                 TALLOC_FREE(state);
2781                 dcerpc_transport_dead(p, status);
2782                 return;
2783         }
2784
2785         TALLOC_FREE(state);
2786 }