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