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