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