s4:librpc/rpc: use the correct ndr flags in dcerpc_ndr_validate_in()
[nivanova/samba-autobuild/.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 "../lib/util/dlinklist.h"
25 #include "lib/events/events.h"
26 #include "librpc/rpc/dcerpc.h"
27 #include "librpc/rpc/dcerpc_proto.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "libcli/composite/composite.h"
31 #include "auth/gensec/gensec.h"
32 #include "param/param.h"
33
34 _PUBLIC_ NTSTATUS dcerpc_init(struct loadparm_context *lp_ctx)
35 {
36         return gensec_init(lp_ctx);
37 }
38
39 static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status);
40 static void dcerpc_ship_next_request(struct dcerpc_connection *c);
41
42 /* destroy a dcerpc connection */
43 static int dcerpc_connection_destructor(struct dcerpc_connection *conn)
44 {
45         if (conn->dead) {
46                 conn->free_skipped = true;
47                 return -1;
48         }
49         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
50         return 0;
51 }
52
53
54 /* initialise a dcerpc connection. 
55    the event context is optional
56 */
57 static struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 
58                                                  struct tevent_context *ev)
59 {
60         struct dcerpc_connection *c;
61
62         c = talloc_zero(mem_ctx, struct dcerpc_connection);
63         if (!c) {
64                 return NULL;
65         }
66
67         c->event_ctx = ev;
68
69         if (c->event_ctx == NULL) {
70                 talloc_free(c);
71                 return NULL;
72         }
73
74         c->call_id = 1;
75         c->security_state.auth_info = NULL;
76         c->security_state.session_key = dcerpc_generic_session_key;
77         c->security_state.generic_state = NULL;
78         c->binding_string = NULL;
79         c->flags = 0;
80         c->srv_max_xmit_frag = 0;
81         c->srv_max_recv_frag = 0;
82         c->pending = NULL;
83
84         talloc_set_destructor(c, dcerpc_connection_destructor);
85
86         return c;
87 }
88
89 /* initialise a dcerpc pipe. */
90 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
91 {
92         struct dcerpc_pipe *p;
93
94         p = talloc(mem_ctx, struct dcerpc_pipe);
95         if (!p) {
96                 return NULL;
97         }
98
99         p->conn = dcerpc_connection_init(p, ev);
100         if (p->conn == NULL) {
101                 talloc_free(p);
102                 return NULL;
103         }
104
105         p->last_fault_code = 0;
106         p->context_id = 0;
107         p->request_timeout = DCERPC_REQUEST_TIMEOUT;
108         p->binding = NULL;
109
110         ZERO_STRUCT(p->syntax);
111         ZERO_STRUCT(p->transfer_syntax);
112
113         if (DEBUGLVL(100)) {
114                 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
115         }
116
117         p->binding_handle = talloc(p, struct dcerpc_binding_handle);
118         if (p->binding_handle == NULL) {
119                 talloc_free(p);
120                 return NULL;
121         }
122         p->binding_handle->private_data = p;
123
124         return p;
125 }
126
127
128 /* 
129    choose the next call id to use
130 */
131 static uint32_t next_call_id(struct dcerpc_connection *c)
132 {
133         c->call_id++;
134         if (c->call_id == 0) {
135                 c->call_id++;
136         }
137         return c->call_id;
138 }
139
140 /**
141   setup for a ndr pull, also setting up any flags from the binding string
142 */
143 static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_connection *c, 
144                                             DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
145 {
146         struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
147
148         if (ndr == NULL) return ndr;
149
150         if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
151                 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
152         }
153
154         if (c->flags & DCERPC_NDR_REF_ALLOC) {
155                 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
156         }
157
158         if (c->flags & DCERPC_NDR64) {
159                 ndr->flags |= LIBNDR_FLAG_NDR64;
160         }
161
162         return ndr;
163 }
164
165 /* 
166    parse a data blob into a ncacn_packet structure. This handles both
167    input and output packets
168 */
169 static NTSTATUS ncacn_pull(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
170                             struct ncacn_packet *pkt)
171 {
172         struct ndr_pull *ndr;
173         enum ndr_err_code ndr_err;
174
175         ndr = ndr_pull_init_flags(c, blob, mem_ctx);
176         if (!ndr) {
177                 return NT_STATUS_NO_MEMORY;
178         }
179
180         if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
181                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
182         }
183
184         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
185         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
186                 return ndr_map_error2ntstatus(ndr_err);
187         }
188
189         return NT_STATUS_OK;
190 }
191
192 /* 
193    parse the authentication information on a dcerpc response packet
194 */
195 static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx, 
196                                         DATA_BLOB *raw_packet,
197                                         struct ncacn_packet *pkt)
198 {
199         NTSTATUS status;
200         struct dcerpc_auth auth;
201         uint32_t auth_length;
202
203         if (!c->security_state.auth_info ||
204             !c->security_state.generic_state) {
205                 return NT_STATUS_OK;
206         }
207
208         switch (c->security_state.auth_info->auth_level) {
209         case DCERPC_AUTH_LEVEL_PRIVACY:
210         case DCERPC_AUTH_LEVEL_INTEGRITY:
211                 break;
212
213         case DCERPC_AUTH_LEVEL_CONNECT:
214                 if (pkt->auth_length != 0) {
215                         break;
216                 }
217                 return NT_STATUS_OK;
218         case DCERPC_AUTH_LEVEL_NONE:
219                 if (pkt->auth_length != 0) {
220                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
221                 }
222                 return NT_STATUS_OK;
223
224         default:
225                 return NT_STATUS_INVALID_LEVEL;
226         }
227
228         status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
229                                           &pkt->u.response.stub_and_verifier,
230                                           &auth, &auth_length, false);
231         NT_STATUS_NOT_OK_RETURN(status);
232
233         pkt->u.response.stub_and_verifier.length -= auth_length;
234
235         /* check signature or unseal the packet */
236         switch (c->security_state.auth_info->auth_level) {
237         case DCERPC_AUTH_LEVEL_PRIVACY:
238                 status = gensec_unseal_packet(c->security_state.generic_state, 
239                                               mem_ctx, 
240                                               raw_packet->data + DCERPC_REQUEST_LENGTH,
241                                               pkt->u.response.stub_and_verifier.length, 
242                                               raw_packet->data,
243                                               raw_packet->length - auth.credentials.length,
244                                               &auth.credentials);
245                 memcpy(pkt->u.response.stub_and_verifier.data,
246                        raw_packet->data + DCERPC_REQUEST_LENGTH,
247                        pkt->u.response.stub_and_verifier.length);
248                 break;
249                 
250         case DCERPC_AUTH_LEVEL_INTEGRITY:
251                 status = gensec_check_packet(c->security_state.generic_state, 
252                                              mem_ctx, 
253                                              pkt->u.response.stub_and_verifier.data, 
254                                              pkt->u.response.stub_and_verifier.length, 
255                                              raw_packet->data,
256                                              raw_packet->length - auth.credentials.length,
257                                              &auth.credentials);
258                 break;
259
260         case DCERPC_AUTH_LEVEL_CONNECT:
261                 /* for now we ignore possible signatures here */
262                 status = NT_STATUS_OK;
263                 break;
264
265         default:
266                 status = NT_STATUS_INVALID_LEVEL;
267                 break;
268         }
269         
270         /* remove the indicated amount of padding */
271         if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
272                 return NT_STATUS_INFO_LENGTH_MISMATCH;
273         }
274         pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
275
276         return status;
277 }
278
279
280 /* 
281    push a dcerpc request packet into a blob, possibly signing it.
282 */
283 static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, 
284                                          DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
285                                          size_t sig_size,
286                                          struct ncacn_packet *pkt)
287 {
288         NTSTATUS status;
289         struct ndr_push *ndr;
290         DATA_BLOB creds2;
291         size_t payload_length;
292         enum ndr_err_code ndr_err;
293         size_t hdr_size = DCERPC_REQUEST_LENGTH;
294
295         /* non-signed packets are simpler */
296         if (sig_size == 0) {
297                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
298         }
299
300         switch (c->security_state.auth_info->auth_level) {
301         case DCERPC_AUTH_LEVEL_PRIVACY:
302         case DCERPC_AUTH_LEVEL_INTEGRITY:
303                 break;
304
305         case DCERPC_AUTH_LEVEL_CONNECT:
306                 /* TODO: let the gensec mech decide if it wants to generate a signature */
307                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
308
309         case DCERPC_AUTH_LEVEL_NONE:
310                 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
311
312         default:
313                 return NT_STATUS_INVALID_LEVEL;
314         }
315
316         ndr = ndr_push_init_ctx(mem_ctx);
317         if (!ndr) {
318                 return NT_STATUS_NO_MEMORY;
319         }
320
321         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
322                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
323         }
324
325         if (c->flags & DCERPC_NDR64) {
326                 ndr->flags |= LIBNDR_FLAG_NDR64;
327         }
328
329         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
330                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
331                 hdr_size += 16;
332         }
333
334         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
335         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
336                 return ndr_map_error2ntstatus(ndr_err);
337         }
338
339         /* pad to 16 byte multiple in the payload portion of the
340            packet. This matches what w2k3 does. Note that we can't use
341            ndr_push_align() as that is relative to the start of the
342            whole packet, whereas w2k8 wants it relative to the start
343            of the stub */
344         c->security_state.auth_info->auth_pad_length =
345                 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
346         ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
347         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
348                 return ndr_map_error2ntstatus(ndr_err);
349         }
350
351         payload_length = pkt->u.request.stub_and_verifier.length + 
352                 c->security_state.auth_info->auth_pad_length;
353
354         /* we start without signature, it will appended later */
355         c->security_state.auth_info->credentials = data_blob(NULL,0);
356
357         /* add the auth verifier */
358         ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info);
359         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
360                 return ndr_map_error2ntstatus(ndr_err);
361         }
362
363         /* extract the whole packet as a blob */
364         *blob = ndr_push_blob(ndr);
365
366         /*
367          * Setup the frag and auth length in the packet buffer.
368          * This is needed if the GENSEC mech does AEAD signing
369          * of the packet headers. The signature itself will be
370          * appended later.
371          */
372         dcerpc_set_frag_length(blob, blob->length + sig_size);
373         dcerpc_set_auth_length(blob, sig_size);
374
375         /* sign or seal the packet */
376         switch (c->security_state.auth_info->auth_level) {
377         case DCERPC_AUTH_LEVEL_PRIVACY:
378                 status = gensec_seal_packet(c->security_state.generic_state, 
379                                             mem_ctx, 
380                                             blob->data + hdr_size,
381                                             payload_length,
382                                             blob->data,
383                                             blob->length,
384                                             &creds2);
385                 if (!NT_STATUS_IS_OK(status)) {
386                         return status;
387                 }
388                 break;
389
390         case DCERPC_AUTH_LEVEL_INTEGRITY:
391                 status = gensec_sign_packet(c->security_state.generic_state, 
392                                             mem_ctx, 
393                                             blob->data + hdr_size,
394                                             payload_length, 
395                                             blob->data,
396                                             blob->length,
397                                             &creds2);
398                 if (!NT_STATUS_IS_OK(status)) {
399                         return status;
400                 }
401                 break;
402
403         default:
404                 status = NT_STATUS_INVALID_LEVEL;
405                 break;
406         }
407
408         if (creds2.length != sig_size) {
409                 /* this means the sig_size estimate for the signature
410                    was incorrect. We have to correct the packet
411                    sizes. That means we could go over the max fragment
412                    length */
413                 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
414                         (unsigned) creds2.length,
415                         (unsigned) sig_size,
416                         (unsigned) c->security_state.auth_info->auth_pad_length,
417                         (unsigned) pkt->u.request.stub_and_verifier.length));
418                 dcerpc_set_frag_length(blob, blob->length + creds2.length);
419                 dcerpc_set_auth_length(blob, creds2.length);
420         }
421
422         if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
423                 return NT_STATUS_NO_MEMORY;
424         }
425
426         return NT_STATUS_OK;
427 }
428
429
430 /* 
431    fill in the fixed values in a dcerpc header 
432 */
433 static void init_ncacn_hdr(struct dcerpc_connection *c, struct ncacn_packet *pkt)
434 {
435         pkt->rpc_vers = 5;
436         pkt->rpc_vers_minor = 0;
437         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
438                 pkt->drep[0] = 0;
439         } else {
440                 pkt->drep[0] = DCERPC_DREP_LE;
441         }
442         pkt->drep[1] = 0;
443         pkt->drep[2] = 0;
444         pkt->drep[3] = 0;
445 }
446
447 /*
448   map a bind nak reason to a NTSTATUS
449 */
450 static NTSTATUS dcerpc_map_reason(uint16_t reason)
451 {
452         switch (reason) {
453         case DCERPC_BIND_REASON_ASYNTAX:
454                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
455         case DCERPC_BIND_REASON_INVALID_AUTH_TYPE:
456                 return NT_STATUS_INVALID_PARAMETER;
457         }
458         return NT_STATUS_UNSUCCESSFUL;
459 }
460
461 /*
462   a bind or alter context has failed
463 */
464 static void dcerpc_composite_fail(struct rpc_request *req)
465 {
466         struct composite_context *c = talloc_get_type(req->async.private_data, 
467                                                       struct composite_context);
468         composite_error(c, req->status);
469 }
470
471 /*
472   remove requests from the pending or queued queues
473  */
474 static int dcerpc_req_dequeue(struct rpc_request *req)
475 {
476         switch (req->state) {
477         case RPC_REQUEST_QUEUED:
478                 DLIST_REMOVE(req->p->conn->request_queue, req);
479                 break;
480         case RPC_REQUEST_PENDING:
481                 DLIST_REMOVE(req->p->conn->pending, req);
482                 break;
483         case RPC_REQUEST_DONE:
484                 break;
485         }
486         return 0;
487 }
488
489
490 /*
491   mark the dcerpc connection dead. All outstanding requests get an error
492 */
493 static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status)
494 {
495         if (conn->dead) return;
496
497         conn->dead = true;
498
499         if (conn->transport.shutdown_pipe) {
500                 conn->transport.shutdown_pipe(conn, status);
501         }
502
503         /* all pending requests get the error */
504         while (conn->pending) {
505                 struct rpc_request *req = conn->pending;
506                 dcerpc_req_dequeue(req);
507                 req->state = RPC_REQUEST_DONE;
508                 req->status = status;
509                 if (req->async.callback) {
510                         req->async.callback(req);
511                 }
512         }       
513
514         talloc_set_destructor(conn, NULL);
515         if (conn->free_skipped) {
516                 talloc_free(conn);
517         }
518 }
519
520 /*
521   forward declarations of the recv_data handlers for the types of
522   packets we need to handle
523 */
524 static void dcerpc_request_recv_data(struct dcerpc_connection *c, 
525                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
526
527 /*
528   receive a dcerpc reply from the transport. Here we work out what
529   type of reply it is (normal request, bind or alter context) and
530   dispatch to the appropriate handler
531 */
532 static void dcerpc_recv_data(struct dcerpc_connection *conn, DATA_BLOB *blob, NTSTATUS status)
533 {
534         struct ncacn_packet pkt;
535
536         if (NT_STATUS_IS_OK(status) && blob->length == 0) {
537                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
538         }
539
540         /* the transport may be telling us of a severe error, such as
541            a dropped socket */
542         if (!NT_STATUS_IS_OK(status)) {
543                 data_blob_free(blob);
544                 dcerpc_connection_dead(conn, status);
545                 return;
546         }
547
548         /* parse the basic packet to work out what type of response this is */
549         status = ncacn_pull(conn, blob, blob->data, &pkt);
550         if (!NT_STATUS_IS_OK(status)) {
551                 data_blob_free(blob);
552                 dcerpc_connection_dead(conn, status);
553         }
554
555         dcerpc_request_recv_data(conn, blob, &pkt);
556 }
557
558 /*
559   Receive a bind reply from the transport
560 */
561 static void dcerpc_bind_recv_handler(struct rpc_request *req, 
562                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
563 {
564         struct composite_context *c;
565         struct dcerpc_connection *conn;
566
567         c = talloc_get_type(req->async.private_data, struct composite_context);
568
569         if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
570                 DEBUG(2,("dcerpc: bind_nak reason %d\n",
571                          pkt->u.bind_nak.reject_reason));
572                 composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
573                                                      reject_reason));
574                 return;
575         }
576
577         if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
578             (pkt->u.bind_ack.num_results == 0) ||
579             (pkt->u.bind_ack.ctx_list[0].result != 0)) {
580                 req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
581                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
582                 return;
583         }
584
585         conn = req->p->conn;
586
587         conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
588         conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
589
590         if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
591             (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
592                 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
593         }
594
595         if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
596             (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
597                 conn->flags |= DCERPC_HEADER_SIGNING;
598         }
599
600         /* the bind_ack might contain a reply set of credentials */
601         if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
602                 NTSTATUS status;
603                 uint32_t auth_length;
604                 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
605                                                   conn->security_state.auth_info, &auth_length, true);
606                 if (!NT_STATUS_IS_OK(status)) {
607                         composite_error(c, status);
608                         return;
609                 }
610         }
611
612         req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
613
614         composite_done(c);
615 }
616
617 /*
618   handle timeouts of individual dcerpc requests
619 */
620 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
621                                    struct timeval t, void *private_data)
622 {
623         struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
624
625         if (req->ignore_timeout) {
626                 dcerpc_req_dequeue(req);
627                 req->state = RPC_REQUEST_DONE;
628                 req->status = NT_STATUS_IO_TIMEOUT;
629                 if (req->async.callback) {
630                         req->async.callback(req);
631                 }
632                 return;
633         }
634
635         dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
636 }
637
638 /*
639   send a async dcerpc bind request
640 */
641 struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
642                                            TALLOC_CTX *mem_ctx,
643                                            const struct ndr_syntax_id *syntax,
644                                            const struct ndr_syntax_id *transfer_syntax)
645 {
646         struct composite_context *c;
647         struct ncacn_packet pkt;
648         DATA_BLOB blob;
649         struct rpc_request *req;
650
651         c = composite_create(mem_ctx,p->conn->event_ctx);
652         if (c == NULL) return NULL;
653
654         c->private_data = p;
655
656         p->syntax = *syntax;
657         p->transfer_syntax = *transfer_syntax;
658
659         init_ncacn_hdr(p->conn, &pkt);
660
661         pkt.ptype = DCERPC_PKT_BIND;
662         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
663         pkt.call_id = p->conn->call_id;
664         pkt.auth_length = 0;
665
666         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
667                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
668         }
669
670         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
671                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
672         }
673
674         pkt.u.bind.max_xmit_frag = 5840;
675         pkt.u.bind.max_recv_frag = 5840;
676         pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
677         pkt.u.bind.num_contexts = 1;
678         pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
679         if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
680         pkt.u.bind.ctx_list[0].context_id = p->context_id;
681         pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
682         pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
683         pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
684         pkt.u.bind.auth_info = data_blob(NULL, 0);
685
686         /* construct the NDR form of the packet */
687         c->status = ncacn_push_auth(&blob, c, &pkt,
688                                     p->conn->security_state.auth_info);
689         if (!composite_is_ok(c)) return c;
690
691         p->conn->transport.recv_data = dcerpc_recv_data;
692
693         /*
694          * we allocate a dcerpc_request so we can be in the same
695          * request queue as normal requests
696          */
697         req = talloc_zero(c, struct rpc_request);
698         if (composite_nomem(req, c)) return c;
699
700         req->state = RPC_REQUEST_PENDING;
701         req->call_id = pkt.call_id;
702         req->async.private_data = c;
703         req->async.callback = dcerpc_composite_fail;
704         req->p = p;
705         req->recv_handler = dcerpc_bind_recv_handler;
706         DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
707         talloc_set_destructor(req, dcerpc_req_dequeue);
708
709         c->status = p->conn->transport.send_request(p->conn, &blob,
710                                                     true);
711         if (!composite_is_ok(c)) return c;
712
713         event_add_timed(c->event_ctx, req,
714                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
715                         dcerpc_timeout_handler, req);
716
717         return c;
718 }
719
720 /*
721   recv side of async dcerpc bind request
722 */
723 NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
724 {
725         NTSTATUS result = composite_wait(ctx);
726         talloc_free(ctx);
727         return result;
728 }
729
730 /* 
731    perform a continued bind (and auth3)
732 */
733 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
734                       TALLOC_CTX *mem_ctx)
735 {
736         struct ncacn_packet pkt;
737         NTSTATUS status;
738         DATA_BLOB blob;
739
740         init_ncacn_hdr(p->conn, &pkt);
741
742         pkt.ptype = DCERPC_PKT_AUTH3;
743         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
744         pkt.call_id = next_call_id(p->conn);
745         pkt.auth_length = 0;
746         pkt.u.auth3.auth_info = data_blob(NULL, 0);
747
748         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
749                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
750         }
751
752         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
753                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
754         }
755
756         /* construct the NDR form of the packet */
757         status = ncacn_push_auth(&blob, mem_ctx,
758                                  &pkt,
759                                  p->conn->security_state.auth_info);
760         if (!NT_STATUS_IS_OK(status)) {
761                 return status;
762         }
763
764         /* send it on its way */
765         status = p->conn->transport.send_request(p->conn, &blob, false);
766         if (!NT_STATUS_IS_OK(status)) {
767                 return status;
768         }
769
770         return NT_STATUS_OK;    
771 }
772
773
774 /*
775   process a fragment received from the transport layer during a
776   request
777
778   This function frees the data 
779 */
780 static void dcerpc_request_recv_data(struct dcerpc_connection *c, 
781                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
782 {
783         struct rpc_request *req;
784         unsigned int length;
785         NTSTATUS status = NT_STATUS_OK;
786
787         /*
788           if this is an authenticated connection then parse and check
789           the auth info. We have to do this before finding the
790           matching packet, as the request structure might have been
791           removed due to a timeout, but if it has been we still need
792           to run the auth routines so that we don't get the sign/seal
793           info out of step with the server
794         */
795         if (c->security_state.auth_info && c->security_state.generic_state &&
796             pkt->ptype == DCERPC_PKT_RESPONSE) {
797                 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
798         }
799
800         /* find the matching request */
801         for (req=c->pending;req;req=req->next) {
802                 if (pkt->call_id == req->call_id) break;
803         }
804
805 #if 0
806         /* useful for testing certain vendors RPC servers */
807         if (req == NULL && c->pending && pkt->call_id == 0) {
808                 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
809                 req = c->pending;
810         }
811 #endif
812
813         if (req == NULL) {
814                 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
815                 data_blob_free(raw_packet);
816                 return;
817         }
818
819         talloc_steal(req, raw_packet->data);
820
821         if (req->recv_handler != NULL) {
822                 dcerpc_req_dequeue(req);
823                 req->state = RPC_REQUEST_DONE;
824                 req->recv_handler(req, raw_packet, pkt);
825                 return;
826         }
827
828         if (pkt->ptype == DCERPC_PKT_FAULT) {
829                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
830                 req->fault_code = pkt->u.fault.status;
831                 req->status = NT_STATUS_NET_WRITE_FAULT;
832                 goto req_done;
833         }
834
835         if (pkt->ptype != DCERPC_PKT_RESPONSE) {
836                 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
837                          (int)pkt->ptype)); 
838                 req->fault_code = DCERPC_FAULT_OTHER;
839                 req->status = NT_STATUS_NET_WRITE_FAULT;
840                 goto req_done;
841         }
842
843         /* now check the status from the auth routines, and if it failed then fail
844            this request accordingly */
845         if (!NT_STATUS_IS_OK(status)) {
846                 req->status = status;
847                 goto req_done;
848         }
849
850         length = pkt->u.response.stub_and_verifier.length;
851
852         if (length > 0) {
853                 req->payload.data = talloc_realloc(req, 
854                                                    req->payload.data, 
855                                                    uint8_t,
856                                                    req->payload.length + length);
857                 if (!req->payload.data) {
858                         req->status = NT_STATUS_NO_MEMORY;
859                         goto req_done;
860                 }
861                 memcpy(req->payload.data+req->payload.length, 
862                        pkt->u.response.stub_and_verifier.data, length);
863                 req->payload.length += length;
864         }
865
866         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
867                 c->transport.send_read(c);
868                 return;
869         }
870
871         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
872                 req->flags |= DCERPC_PULL_BIGENDIAN;
873         } else {
874                 req->flags &= ~DCERPC_PULL_BIGENDIAN;
875         }
876
877
878 req_done:
879         /* we've got the full payload */
880         req->state = RPC_REQUEST_DONE;
881         DLIST_REMOVE(c->pending, req);
882
883         if (c->request_queue != NULL) {
884                 /* We have to look at shipping further requests before calling
885                  * the async function, that one might close the pipe */
886                 dcerpc_ship_next_request(c);
887         }
888
889         if (req->async.callback) {
890                 req->async.callback(req);
891         }
892 }
893
894 /*
895   perform the send side of a async dcerpc request
896 */
897 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, 
898                                                const struct GUID *object,
899                                                uint16_t opnum,
900                                                bool async,
901                                                DATA_BLOB *stub_data)
902 {
903         struct rpc_request *req;
904
905         p->conn->transport.recv_data = dcerpc_recv_data;
906
907         req = talloc(p, struct rpc_request);
908         if (req == NULL) {
909                 return NULL;
910         }
911
912         req->p = p;
913         req->call_id = next_call_id(p->conn);
914         req->status = NT_STATUS_OK;
915         req->state = RPC_REQUEST_QUEUED;
916         req->payload = data_blob(NULL, 0);
917         req->flags = 0;
918         req->fault_code = 0;
919         req->async_call = async;
920         req->ignore_timeout = false;
921         req->async.callback = NULL;
922         req->async.private_data = NULL;
923         req->recv_handler = NULL;
924
925         if (object != NULL) {
926                 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
927                 if (req->object == NULL) {
928                         talloc_free(req);
929                         return NULL;
930                 }
931         } else {
932                 req->object = NULL;
933         }
934
935         req->opnum = opnum;
936         req->request_data.length = stub_data->length;
937         req->request_data.data = talloc_reference(req, stub_data->data);
938         if (req->request_data.length && req->request_data.data == NULL) {
939                 return NULL;
940         }
941
942         DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
943         talloc_set_destructor(req, dcerpc_req_dequeue);
944
945         dcerpc_ship_next_request(p->conn);
946
947         if (p->request_timeout) {
948                 event_add_timed(dcerpc_event_context(p), req, 
949                                 timeval_current_ofs(p->request_timeout, 0), 
950                                 dcerpc_timeout_handler, req);
951         }
952
953         return req;
954 }
955
956 /*
957   Send a request using the transport
958 */
959
960 static void dcerpc_ship_next_request(struct dcerpc_connection *c)
961 {
962         struct rpc_request *req;
963         struct dcerpc_pipe *p;
964         DATA_BLOB *stub_data;
965         struct ncacn_packet pkt;
966         DATA_BLOB blob;
967         uint32_t remaining, chunk_size;
968         bool first_packet = true;
969         size_t sig_size = 0;
970
971         req = c->request_queue;
972         if (req == NULL) {
973                 return;
974         }
975
976         p = req->p;
977         stub_data = &req->request_data;
978
979         if (!req->async_call && (c->pending != NULL)) {
980                 return;
981         }
982
983         DLIST_REMOVE(c->request_queue, req);
984         DLIST_ADD(c->pending, req);
985         req->state = RPC_REQUEST_PENDING;
986
987         init_ncacn_hdr(p->conn, &pkt);
988
989         remaining = stub_data->length;
990
991         /* we can write a full max_recv_frag size, minus the dcerpc
992            request header size */
993         chunk_size = p->conn->srv_max_recv_frag;
994         chunk_size -= DCERPC_REQUEST_LENGTH;
995         if (c->security_state.auth_info &&
996             c->security_state.generic_state) {
997                 sig_size = gensec_sig_size(c->security_state.generic_state,
998                                            p->conn->srv_max_recv_frag);
999                 if (sig_size) {
1000                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1001                         chunk_size -= sig_size;
1002                 }
1003         }
1004         chunk_size -= (chunk_size % 16);
1005
1006         pkt.ptype = DCERPC_PKT_REQUEST;
1007         pkt.call_id = req->call_id;
1008         pkt.auth_length = 0;
1009         pkt.pfc_flags = 0;
1010         pkt.u.request.alloc_hint = remaining;
1011         pkt.u.request.context_id = p->context_id;
1012         pkt.u.request.opnum = req->opnum;
1013
1014         if (req->object) {
1015                 pkt.u.request.object.object = *req->object;
1016                 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1017                 chunk_size -= ndr_size_GUID(req->object,0);
1018         }
1019
1020         /* we send a series of pdus without waiting for a reply */
1021         while (remaining > 0 || first_packet) {
1022                 uint32_t chunk = MIN(chunk_size, remaining);
1023                 bool last_frag = false;
1024                 bool do_trans = false;
1025
1026                 first_packet = false;
1027                 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1028
1029                 if (remaining == stub_data->length) {
1030                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1031                 }
1032                 if (chunk == remaining) {
1033                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1034                         last_frag = true;
1035                 }
1036
1037                 pkt.u.request.stub_and_verifier.data = stub_data->data + 
1038                         (stub_data->length - remaining);
1039                 pkt.u.request.stub_and_verifier.length = chunk;
1040
1041                 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1042                 if (!NT_STATUS_IS_OK(req->status)) {
1043                         req->state = RPC_REQUEST_DONE;
1044                         DLIST_REMOVE(p->conn->pending, req);
1045                         return;
1046                 }
1047
1048                 if (last_frag && !req->async_call) {
1049                         do_trans = true;
1050                 }
1051
1052                 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans);
1053                 if (!NT_STATUS_IS_OK(req->status)) {
1054                         req->state = RPC_REQUEST_DONE;
1055                         DLIST_REMOVE(p->conn->pending, req);
1056                         return;
1057                 }               
1058
1059                 if (last_frag && !do_trans) {
1060                         req->status = p->conn->transport.send_read(p->conn);
1061                         if (!NT_STATUS_IS_OK(req->status)) {
1062                                 req->state = RPC_REQUEST_DONE;
1063                                 DLIST_REMOVE(p->conn->pending, req);
1064                                 return;
1065                         }
1066                 }
1067
1068                 remaining -= chunk;
1069         }
1070 }
1071
1072 /*
1073   return the event context for a dcerpc pipe
1074   used by callers who wish to operate asynchronously
1075 */
1076 _PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p)
1077 {
1078         return p->conn->event_ctx;
1079 }
1080
1081
1082
1083 /*
1084   perform the receive side of a async dcerpc request
1085 */
1086 NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1087                              TALLOC_CTX *mem_ctx,
1088                              DATA_BLOB *stub_data)
1089 {
1090         NTSTATUS status;
1091
1092         while (req->state != RPC_REQUEST_DONE) {
1093                 struct tevent_context *ctx = dcerpc_event_context(req->p);
1094                 if (event_loop_once(ctx) != 0) {
1095                         return NT_STATUS_CONNECTION_DISCONNECTED;
1096                 }
1097         }
1098         *stub_data = req->payload;
1099         status = req->status;
1100         if (stub_data->data) {
1101                 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1102         }
1103         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1104                 req->p->last_fault_code = req->fault_code;
1105         }
1106         talloc_unlink(talloc_parent(req), req);
1107         return status;
1108 }
1109
1110 /*
1111   perform a full request/response pair on a dcerpc pipe
1112 */
1113 NTSTATUS dcerpc_request(struct dcerpc_pipe *p, 
1114                         struct GUID *object,
1115                         uint16_t opnum,
1116                         TALLOC_CTX *mem_ctx,
1117                         DATA_BLOB *stub_data_in,
1118                         DATA_BLOB *stub_data_out)
1119 {
1120         struct rpc_request *req;
1121
1122         req = dcerpc_request_send(p, object, opnum, false, stub_data_in);
1123         if (req == NULL) {
1124                 return NT_STATUS_NO_MEMORY;
1125         }
1126
1127         return dcerpc_request_recv(req, mem_ctx, stub_data_out);
1128 }
1129
1130
1131 /*
1132   this is a paranoid NDR validator. For every packet we push onto the wire
1133   we pull it back again, then push it again. Then we compare the raw NDR data
1134   for that to the NDR we initially generated. If they don't match then we know
1135   we must have a bug in either the pull or push side of our code
1136 */
1137 static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c, 
1138                                        TALLOC_CTX *mem_ctx,
1139                                        DATA_BLOB blob,
1140                                        size_t struct_size,
1141                                        ndr_push_flags_fn_t ndr_push,
1142                                        ndr_pull_flags_fn_t ndr_pull)
1143 {
1144         void *st;
1145         struct ndr_pull *pull;
1146         struct ndr_push *push;
1147         DATA_BLOB blob2;
1148         enum ndr_err_code ndr_err;
1149
1150         st = talloc_size(mem_ctx, struct_size);
1151         if (!st) {
1152                 return NT_STATUS_NO_MEMORY;
1153         }
1154
1155         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1156         if (!pull) {
1157                 return NT_STATUS_NO_MEMORY;
1158         }
1159         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1160
1161         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1162                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1163         }
1164
1165         if (c->flags & DCERPC_NDR64) {
1166                 pull->flags |= LIBNDR_FLAG_NDR64;
1167         }
1168
1169         ndr_err = ndr_pull(pull, NDR_IN, st);
1170         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1171                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1172                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1173                                          "failed input validation pull - %s",
1174                                          nt_errstr(status));
1175                 return ndr_map_error2ntstatus(ndr_err);
1176         }
1177
1178         push = ndr_push_init_ctx(mem_ctx);
1179         if (!push) {
1180                 return NT_STATUS_NO_MEMORY;
1181         }       
1182
1183         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1184                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1185         }
1186
1187         if (c->flags & DCERPC_NDR64) {
1188                 push->flags |= LIBNDR_FLAG_NDR64;
1189         }
1190
1191         ndr_err = ndr_push(push, NDR_IN, st);
1192         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1193                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1194                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1195                                          "failed input validation push - %s",
1196                                          nt_errstr(status));
1197                 return ndr_map_error2ntstatus(ndr_err);
1198         }
1199
1200         blob2 = ndr_push_blob(push);
1201
1202         if (data_blob_cmp(&blob, &blob2) != 0) {
1203                 DEBUG(3,("original:\n"));
1204                 dump_data(3, blob.data, blob.length);
1205                 DEBUG(3,("secondary:\n"));
1206                 dump_data(3, blob2.data, blob2.length);
1207                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1208                                          "failed input validation blobs doesn't match");
1209                 return ndr_map_error2ntstatus(ndr_err);
1210         }
1211
1212         return NT_STATUS_OK;
1213 }
1214
1215 /*
1216   this is a paranoid NDR input validator. For every packet we pull
1217   from the wire we push it back again then pull and push it
1218   again. Then we compare the raw NDR data for that to the NDR we
1219   initially generated. If they don't match then we know we must have a
1220   bug in either the pull or push side of our code
1221 */
1222 static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c,
1223                                         struct ndr_pull *pull_in,
1224                                         void *struct_ptr,
1225                                         size_t struct_size,
1226                                         ndr_push_flags_fn_t ndr_push,
1227                                         ndr_pull_flags_fn_t ndr_pull,
1228                                         ndr_print_function_t ndr_print)
1229 {
1230         void *st;
1231         struct ndr_pull *pull;
1232         struct ndr_push *push;
1233         DATA_BLOB blob, blob2;
1234         TALLOC_CTX *mem_ctx = pull_in;
1235         char *s1, *s2;
1236         enum ndr_err_code ndr_err;
1237
1238         st = talloc_size(mem_ctx, struct_size);
1239         if (!st) {
1240                 return NT_STATUS_NO_MEMORY;
1241         }
1242         memcpy(st, struct_ptr, struct_size);
1243
1244         push = ndr_push_init_ctx(mem_ctx);
1245         if (!push) {
1246                 return NT_STATUS_NO_MEMORY;
1247         }       
1248
1249         ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1250         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1251                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1252                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1253                                          "failed output validation push - %s",
1254                                          nt_errstr(status));
1255                 return ndr_map_error2ntstatus(ndr_err);
1256         }
1257
1258         blob = ndr_push_blob(push);
1259
1260         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1261         if (!pull) {
1262                 return NT_STATUS_NO_MEMORY;
1263         }
1264
1265         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1266         ndr_err = ndr_pull(pull, NDR_OUT, st);
1267         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1268                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1269                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1270                                          "failed output validation pull - %s",
1271                                          nt_errstr(status));
1272                 return ndr_map_error2ntstatus(ndr_err);
1273         }
1274
1275         push = ndr_push_init_ctx(mem_ctx);
1276         if (!push) {
1277                 return NT_STATUS_NO_MEMORY;
1278         }       
1279
1280         ndr_err = ndr_push(push, NDR_OUT, st);
1281         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1282                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1283                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1284                                          "failed output validation push2 - %s",
1285                                          nt_errstr(status));
1286                 return ndr_map_error2ntstatus(ndr_err);
1287         }
1288
1289         blob2 = ndr_push_blob(push);
1290
1291         if (data_blob_cmp(&blob, &blob2) != 0) {
1292                 DEBUG(3,("original:\n"));
1293                 dump_data(3, blob.data, blob.length);
1294                 DEBUG(3,("secondary:\n"));
1295                 dump_data(3, blob2.data, blob2.length);
1296                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1297                                          "failed output validation blobs doesn't match");
1298                 return ndr_map_error2ntstatus(ndr_err);
1299         }
1300
1301         /* this checks the printed forms of the two structures, which effectively
1302            tests all of the value() attributes */
1303         s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
1304                                        NDR_OUT, struct_ptr);
1305         s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
1306                                        NDR_OUT, st);
1307         if (strcmp(s1, s2) != 0) {
1308 #if 1
1309                 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
1310 #else
1311                 /* this is sometimes useful */
1312                 printf("VALIDATE ERROR\n");
1313                 file_save("wire.dat", s1, strlen(s1));
1314                 file_save("gen.dat", s2, strlen(s2));
1315                 system("diff -u wire.dat gen.dat");
1316 #endif
1317                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1318                                          "failed output validation strings doesn't match");
1319                 return ndr_map_error2ntstatus(ndr_err);
1320         }
1321
1322         return NT_STATUS_OK;
1323 }
1324
1325
1326 /**
1327  send a rpc request given a dcerpc_call structure 
1328  */
1329 struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p,
1330                                             const struct GUID *object,
1331                                             const struct ndr_interface_table *table,
1332                                             uint32_t opnum,
1333                                             bool async,
1334                                             TALLOC_CTX *mem_ctx,
1335                                             void *r)
1336 {
1337         const struct ndr_interface_call *call;
1338         struct ndr_push *push;
1339         NTSTATUS status;
1340         DATA_BLOB request;
1341         struct rpc_request *req;
1342         enum ndr_err_code ndr_err;
1343
1344         call = &table->calls[opnum];
1345
1346         /* setup for a ndr_push_* call */
1347         push = ndr_push_init_ctx(mem_ctx);
1348         if (!push) {
1349                 return NULL;
1350         }
1351
1352         if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1353                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1354         }
1355
1356         if (p->conn->flags & DCERPC_NDR64) {
1357                 push->flags |= LIBNDR_FLAG_NDR64;
1358         }
1359
1360         /* push the structure into a blob */
1361         ndr_err = call->ndr_push(push, NDR_IN, r);
1362         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1363                 status = ndr_map_error2ntstatus(ndr_err);
1364                 DEBUG(2,("Unable to ndr_push structure in dcerpc_ndr_request_send - %s\n",
1365                          nt_errstr(status)));
1366                 talloc_free(push);
1367                 return NULL;
1368         }
1369
1370         /* retrieve the blob */
1371         request = ndr_push_blob(push);
1372
1373         if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
1374                 status = dcerpc_ndr_validate_in(p->conn, push, request, call->struct_size, 
1375                                                 call->ndr_push, call->ndr_pull);
1376                 if (!NT_STATUS_IS_OK(status)) {
1377                         DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n",
1378                                  nt_errstr(status)));
1379                         talloc_free(push);
1380                         return NULL;
1381                 }
1382         }
1383
1384         DEBUG(10,("rpc request data:\n"));
1385         dump_data(10, request.data, request.length);
1386
1387         /* make the actual dcerpc request */
1388         req = dcerpc_request_send(p, object, opnum, async, &request);
1389
1390         if (req != NULL) {
1391                 req->ndr.table = table;
1392                 req->ndr.opnum = opnum;
1393                 req->ndr.struct_ptr = r;
1394                 req->ndr.mem_ctx = mem_ctx;
1395         }
1396
1397         talloc_free(push);
1398
1399         return req;
1400 }
1401
1402 /*
1403   receive the answer from a dcerpc_ndr_request_send()
1404 */
1405 _PUBLIC_ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req)
1406 {
1407         struct dcerpc_pipe *p = req->p;
1408         NTSTATUS status;
1409         DATA_BLOB response;
1410         struct ndr_pull *pull;
1411         unsigned int flags;
1412         TALLOC_CTX *mem_ctx = req->ndr.mem_ctx;
1413         void *r = req->ndr.struct_ptr;
1414         uint32_t opnum = req->ndr.opnum;
1415         const struct ndr_interface_table *table = req->ndr.table;
1416         const struct ndr_interface_call *call = &table->calls[opnum];
1417         enum ndr_err_code ndr_err;
1418
1419         /* make sure the recv code doesn't free the request, as we
1420            need to grab the flags element before it is freed */
1421         if (talloc_reference(p, req) == NULL) {
1422                 return NT_STATUS_NO_MEMORY;
1423         }
1424
1425         status = dcerpc_request_recv(req, mem_ctx, &response);
1426         if (!NT_STATUS_IS_OK(status)) {
1427                 talloc_unlink(p, req);
1428                 return status;
1429         }
1430
1431         flags = req->flags;
1432
1433         /* prepare for ndr_pull_* */
1434         pull = ndr_pull_init_flags(p->conn, &response, mem_ctx);
1435         if (!pull) {
1436                 talloc_unlink(p, req);
1437                 return NT_STATUS_NO_MEMORY;
1438         }
1439
1440         if (pull->data) {
1441                 pull->data = talloc_steal(pull, pull->data);
1442         }
1443         talloc_unlink(p, req);
1444
1445         if (flags & DCERPC_PULL_BIGENDIAN) {
1446                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1447         }
1448
1449         DEBUG(10,("rpc reply data:\n"));
1450         dump_data(10, pull->data, pull->data_size);
1451
1452         /* pull the structure from the blob */
1453         ndr_err = call->ndr_pull(pull, NDR_OUT, r);
1454         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1455                 status = ndr_map_error2ntstatus(ndr_err);
1456                 dcerpc_log_packet(p->conn->packet_log_dir,
1457                                                   table, opnum, NDR_OUT, 
1458                                                   &response);
1459                 return status;
1460         }
1461
1462         if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
1463                 status = dcerpc_ndr_validate_out(p->conn, pull, r, call->struct_size, 
1464                                                  call->ndr_push, call->ndr_pull, 
1465                                                  call->ndr_print);
1466                 if (!NT_STATUS_IS_OK(status)) {
1467                         dcerpc_log_packet(p->conn->packet_log_dir, 
1468                                                           table, opnum, NDR_OUT, 
1469                                   &response);
1470                         return status;
1471                 }
1472         }
1473
1474         if (pull->offset != pull->data_size) {
1475                 DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n", 
1476                          pull->data_size - pull->offset));
1477                 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
1478                    but it turns out that early versions of NT
1479                    (specifically NT3.1) add junk onto the end of rpc
1480                    packets, so if we want to interoperate at all with
1481                    those versions then we need to ignore this error */
1482         }
1483
1484         /* TODO: make pull context independent from the output mem_ctx and free the pull context */
1485
1486         return NT_STATUS_OK;
1487 }
1488
1489
1490 /*
1491   a useful helper function for synchronous rpc requests 
1492
1493   this can be used when you have ndr push/pull functions in the
1494   standard format
1495 */
1496 _PUBLIC_ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,
1497                             const struct GUID *object,
1498                             const struct ndr_interface_table *table,
1499                             uint32_t opnum, 
1500                             TALLOC_CTX *mem_ctx, 
1501                             void *r)
1502 {
1503         struct rpc_request *req;
1504
1505         req = dcerpc_ndr_request_send(p, object, table, opnum, false, mem_ctx, r);
1506         if (req == NULL) {
1507                 return NT_STATUS_NO_MEMORY;
1508         }
1509
1510         return dcerpc_ndr_request_recv(req);
1511 }
1512
1513
1514 /*
1515   a useful function for retrieving the server name we connected to
1516 */
1517 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
1518 {
1519         if (!p->conn->transport.target_hostname) {
1520                 if (!p->conn->transport.peer_name) {
1521                         return "";
1522                 }
1523                 return p->conn->transport.peer_name(p->conn);
1524         }
1525         return p->conn->transport.target_hostname(p->conn);
1526 }
1527
1528
1529 /*
1530   get the dcerpc auth_level for a open connection
1531 */
1532 uint32_t dcerpc_auth_level(struct dcerpc_connection *c) 
1533 {
1534         uint8_t auth_level;
1535
1536         if (c->flags & DCERPC_SEAL) {
1537                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1538         } else if (c->flags & DCERPC_SIGN) {
1539                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1540         } else if (c->flags & DCERPC_CONNECT) {
1541                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1542         } else {
1543                 auth_level = DCERPC_AUTH_LEVEL_NONE;
1544         }
1545         return auth_level;
1546 }
1547
1548 /*
1549   Receive an alter reply from the transport
1550 */
1551 static void dcerpc_alter_recv_handler(struct rpc_request *req,
1552                                       DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1553 {
1554         struct composite_context *c;
1555         struct dcerpc_pipe *recv_pipe;
1556
1557         c = talloc_get_type(req->async.private_data, struct composite_context);
1558         recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
1559
1560         if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
1561             pkt->u.alter_resp.num_results == 1 &&
1562             pkt->u.alter_resp.ctx_list[0].result != 0) {
1563                 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 
1564                          pkt->u.alter_resp.ctx_list[0].reason));
1565                 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
1566                 return;
1567         }
1568
1569         if (pkt->ptype == DCERPC_PKT_FAULT) {
1570                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1571                 recv_pipe->last_fault_code = pkt->u.fault.status;
1572                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1573                 return;
1574         }
1575
1576         if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
1577             pkt->u.alter_resp.num_results == 0 ||
1578             pkt->u.alter_resp.ctx_list[0].result != 0) {
1579                 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1580                 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1581                 return;
1582         }
1583
1584         /* the alter_resp might contain a reply set of credentials */
1585         if (recv_pipe->conn->security_state.auth_info &&
1586             pkt->u.alter_resp.auth_info.length) {
1587                 struct dcerpc_connection *conn = recv_pipe->conn;
1588                 NTSTATUS status;
1589                 uint32_t auth_length;
1590                 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
1591                                                   conn->security_state.auth_info, &auth_length, true);
1592                 if (!NT_STATUS_IS_OK(status)) {
1593                         composite_error(c, status);
1594                         return;
1595                 }
1596         }
1597
1598         composite_done(c);
1599 }
1600
1601 /* 
1602    send a dcerpc alter_context request
1603 */
1604 struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, 
1605                                                     TALLOC_CTX *mem_ctx,
1606                                                     const struct ndr_syntax_id *syntax,
1607                                                     const struct ndr_syntax_id *transfer_syntax)
1608 {
1609         struct composite_context *c;
1610         struct ncacn_packet pkt;
1611         DATA_BLOB blob;
1612         struct rpc_request *req;
1613
1614         c = composite_create(mem_ctx, p->conn->event_ctx);
1615         if (c == NULL) return NULL;
1616
1617         c->private_data = p;
1618
1619         p->syntax = *syntax;
1620         p->transfer_syntax = *transfer_syntax;
1621
1622         init_ncacn_hdr(p->conn, &pkt);
1623
1624         pkt.ptype = DCERPC_PKT_ALTER;
1625         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1626         pkt.call_id = p->conn->call_id;
1627         pkt.auth_length = 0;
1628
1629         if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1630                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1631         }
1632
1633         if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1634                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1635         }
1636
1637         pkt.u.alter.max_xmit_frag = 5840;
1638         pkt.u.alter.max_recv_frag = 5840;
1639         pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;
1640         pkt.u.alter.num_contexts = 1;
1641         pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);
1642         if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;
1643         pkt.u.alter.ctx_list[0].context_id = p->context_id;
1644         pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
1645         pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
1646         pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1647         pkt.u.alter.auth_info = data_blob(NULL, 0);
1648
1649         /* construct the NDR form of the packet */
1650         c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1651                                     p->conn->security_state.auth_info);
1652         if (!composite_is_ok(c)) return c;
1653
1654         p->conn->transport.recv_data = dcerpc_recv_data;
1655
1656         /*
1657          * we allocate a dcerpc_request so we can be in the same
1658          * request queue as normal requests
1659          */
1660         req = talloc_zero(c, struct rpc_request);
1661         if (composite_nomem(req, c)) return c;
1662
1663         req->state = RPC_REQUEST_PENDING;
1664         req->call_id = pkt.call_id;
1665         req->async.private_data = c;
1666         req->async.callback = dcerpc_composite_fail;
1667         req->p = p;
1668         req->recv_handler = dcerpc_alter_recv_handler;
1669         DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
1670         talloc_set_destructor(req, dcerpc_req_dequeue);
1671
1672         c->status = p->conn->transport.send_request(p->conn, &blob, true);
1673         if (!composite_is_ok(c)) return c;
1674
1675         event_add_timed(c->event_ctx, req,
1676                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1677                         dcerpc_timeout_handler, req);
1678
1679         return c;
1680 }
1681
1682 NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
1683 {
1684         NTSTATUS result = composite_wait(ctx);
1685         talloc_free(ctx);
1686         return result;
1687 }
1688
1689 /* 
1690    send a dcerpc alter_context request
1691 */
1692 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 
1693                               TALLOC_CTX *mem_ctx,
1694                               const struct ndr_syntax_id *syntax,
1695                               const struct ndr_syntax_id *transfer_syntax)
1696 {
1697         struct composite_context *creq;
1698         creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
1699         return dcerpc_alter_context_recv(creq);
1700 }
1701