vfs_catia: add chmod()
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob0def81727a622a5f433c32bb96f3f4efc113d3c4
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client routines
4 * Largely rewritten by Jeremy Allison 2005.
5 * Heavily modified by Simo Sorce 2010.
6 * Copyright Andrew Bartlett 2011.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/netlogon_creds_cli.h"
28 #include "auth_generic.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "rpc_dce.h"
33 #include "cli_pipe.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/credentials/credentials.h"
37 #include "../libcli/smb/smbXcli_base.h"
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_RPC_CLI
42 /********************************************************************
43 Pipe description for a DEBUG
44 ********************************************************************/
45 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
46 struct rpc_pipe_client *cli)
48 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
49 if (result == NULL) {
50 return "pipe";
52 return result;
55 /********************************************************************
56 Rpc pipe call id.
57 ********************************************************************/
59 static uint32 get_rpc_call_id(void)
61 static uint32 call_id = 0;
62 return ++call_id;
65 /*******************************************************************
66 Use SMBreadX to get rest of one fragment's worth of rpc data.
67 Reads the whole size or give an error message
68 ********************************************************************/
70 struct rpc_read_state {
71 struct tevent_context *ev;
72 struct rpc_cli_transport *transport;
73 uint8_t *data;
74 size_t size;
75 size_t num_read;
78 static void rpc_read_done(struct tevent_req *subreq);
80 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
81 struct tevent_context *ev,
82 struct rpc_cli_transport *transport,
83 uint8_t *data, size_t size)
85 struct tevent_req *req, *subreq;
86 struct rpc_read_state *state;
88 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
89 if (req == NULL) {
90 return NULL;
92 state->ev = ev;
93 state->transport = transport;
94 state->data = data;
95 state->size = size;
96 state->num_read = 0;
98 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
100 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
101 transport->priv);
102 if (subreq == NULL) {
103 goto fail;
105 tevent_req_set_callback(subreq, rpc_read_done, req);
106 return req;
108 fail:
109 TALLOC_FREE(req);
110 return NULL;
113 static void rpc_read_done(struct tevent_req *subreq)
115 struct tevent_req *req = tevent_req_callback_data(
116 subreq, struct tevent_req);
117 struct rpc_read_state *state = tevent_req_data(
118 req, struct rpc_read_state);
119 NTSTATUS status;
120 ssize_t received;
122 status = state->transport->read_recv(subreq, &received);
123 TALLOC_FREE(subreq);
124 if (!NT_STATUS_IS_OK(status)) {
125 tevent_req_nterror(req, status);
126 return;
129 state->num_read += received;
130 if (state->num_read == state->size) {
131 tevent_req_done(req);
132 return;
135 subreq = state->transport->read_send(state, state->ev,
136 state->data + state->num_read,
137 state->size - state->num_read,
138 state->transport->priv);
139 if (tevent_req_nomem(subreq, req)) {
140 return;
142 tevent_req_set_callback(subreq, rpc_read_done, req);
145 static NTSTATUS rpc_read_recv(struct tevent_req *req)
147 return tevent_req_simple_recv_ntstatus(req);
150 struct rpc_write_state {
151 struct tevent_context *ev;
152 struct rpc_cli_transport *transport;
153 const uint8_t *data;
154 size_t size;
155 size_t num_written;
158 static void rpc_write_done(struct tevent_req *subreq);
160 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
161 struct tevent_context *ev,
162 struct rpc_cli_transport *transport,
163 const uint8_t *data, size_t size)
165 struct tevent_req *req, *subreq;
166 struct rpc_write_state *state;
168 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
169 if (req == NULL) {
170 return NULL;
172 state->ev = ev;
173 state->transport = transport;
174 state->data = data;
175 state->size = size;
176 state->num_written = 0;
178 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
180 subreq = transport->write_send(state, ev, data, size, transport->priv);
181 if (subreq == NULL) {
182 goto fail;
184 tevent_req_set_callback(subreq, rpc_write_done, req);
185 return req;
186 fail:
187 TALLOC_FREE(req);
188 return NULL;
191 static void rpc_write_done(struct tevent_req *subreq)
193 struct tevent_req *req = tevent_req_callback_data(
194 subreq, struct tevent_req);
195 struct rpc_write_state *state = tevent_req_data(
196 req, struct rpc_write_state);
197 NTSTATUS status;
198 ssize_t written;
200 status = state->transport->write_recv(subreq, &written);
201 TALLOC_FREE(subreq);
202 if (!NT_STATUS_IS_OK(status)) {
203 tevent_req_nterror(req, status);
204 return;
207 state->num_written += written;
209 if (state->num_written == state->size) {
210 tevent_req_done(req);
211 return;
214 subreq = state->transport->write_send(state, state->ev,
215 state->data + state->num_written,
216 state->size - state->num_written,
217 state->transport->priv);
218 if (tevent_req_nomem(subreq, req)) {
219 return;
221 tevent_req_set_callback(subreq, rpc_write_done, req);
224 static NTSTATUS rpc_write_recv(struct tevent_req *req)
226 return tevent_req_simple_recv_ntstatus(req);
230 /****************************************************************************
231 Try and get a PDU's worth of data from current_pdu. If not, then read more
232 from the wire.
233 ****************************************************************************/
235 struct get_complete_frag_state {
236 struct tevent_context *ev;
237 struct rpc_pipe_client *cli;
238 uint16_t frag_len;
239 DATA_BLOB *pdu;
242 static void get_complete_frag_got_header(struct tevent_req *subreq);
243 static void get_complete_frag_got_rest(struct tevent_req *subreq);
245 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
246 struct tevent_context *ev,
247 struct rpc_pipe_client *cli,
248 DATA_BLOB *pdu)
250 struct tevent_req *req, *subreq;
251 struct get_complete_frag_state *state;
252 size_t received;
253 NTSTATUS status;
255 req = tevent_req_create(mem_ctx, &state,
256 struct get_complete_frag_state);
257 if (req == NULL) {
258 return NULL;
260 state->ev = ev;
261 state->cli = cli;
262 state->frag_len = RPC_HEADER_LEN;
263 state->pdu = pdu;
265 received = pdu->length;
266 if (received < RPC_HEADER_LEN) {
267 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
268 status = NT_STATUS_NO_MEMORY;
269 goto post_status;
271 subreq = rpc_read_send(state, state->ev,
272 state->cli->transport,
273 pdu->data + received,
274 RPC_HEADER_LEN - received);
275 if (subreq == NULL) {
276 status = NT_STATUS_NO_MEMORY;
277 goto post_status;
279 tevent_req_set_callback(subreq, get_complete_frag_got_header,
280 req);
281 return req;
284 state->frag_len = dcerpc_get_frag_length(pdu);
285 if (state->frag_len < RPC_HEADER_LEN) {
286 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
287 return tevent_req_post(req, ev);
291 * Ensure we have frag_len bytes of data.
293 if (received < state->frag_len) {
294 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
295 status = NT_STATUS_NO_MEMORY;
296 goto post_status;
298 subreq = rpc_read_send(state, state->ev,
299 state->cli->transport,
300 pdu->data + received,
301 state->frag_len - received);
302 if (subreq == NULL) {
303 status = NT_STATUS_NO_MEMORY;
304 goto post_status;
306 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
307 req);
308 return req;
311 status = NT_STATUS_OK;
312 post_status:
313 if (NT_STATUS_IS_OK(status)) {
314 tevent_req_done(req);
315 } else {
316 tevent_req_nterror(req, status);
318 return tevent_req_post(req, ev);
321 static void get_complete_frag_got_header(struct tevent_req *subreq)
323 struct tevent_req *req = tevent_req_callback_data(
324 subreq, struct tevent_req);
325 struct get_complete_frag_state *state = tevent_req_data(
326 req, struct get_complete_frag_state);
327 NTSTATUS status;
329 status = rpc_read_recv(subreq);
330 TALLOC_FREE(subreq);
331 if (!NT_STATUS_IS_OK(status)) {
332 tevent_req_nterror(req, status);
333 return;
336 state->frag_len = dcerpc_get_frag_length(state->pdu);
337 if (state->frag_len < RPC_HEADER_LEN) {
338 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
339 return;
342 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
343 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
344 return;
348 * We're here in this piece of code because we've read exactly
349 * RPC_HEADER_LEN bytes into state->pdu.
352 subreq = rpc_read_send(state, state->ev, state->cli->transport,
353 state->pdu->data + RPC_HEADER_LEN,
354 state->frag_len - RPC_HEADER_LEN);
355 if (tevent_req_nomem(subreq, req)) {
356 return;
358 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
361 static void get_complete_frag_got_rest(struct tevent_req *subreq)
363 struct tevent_req *req = tevent_req_callback_data(
364 subreq, struct tevent_req);
365 NTSTATUS status;
367 status = rpc_read_recv(subreq);
368 TALLOC_FREE(subreq);
369 if (!NT_STATUS_IS_OK(status)) {
370 tevent_req_nterror(req, status);
371 return;
373 tevent_req_done(req);
376 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
378 return tevent_req_simple_recv_ntstatus(req);
381 /****************************************************************************
382 Do basic authentication checks on an incoming pdu.
383 ****************************************************************************/
385 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
386 struct rpc_pipe_client *cli,
387 struct ncacn_packet *pkt,
388 DATA_BLOB *pdu,
389 uint8_t expected_pkt_type,
390 uint32_t call_id,
391 DATA_BLOB *rdata,
392 DATA_BLOB *reply_pdu)
394 struct dcerpc_response *r;
395 NTSTATUS ret = NT_STATUS_OK;
396 size_t pad_len = 0;
399 * Point the return values at the real data including the RPC
400 * header. Just in case the caller wants it.
402 *rdata = *pdu;
404 /* Ensure we have the correct type. */
405 switch (pkt->ptype) {
406 case DCERPC_PKT_ALTER_RESP:
407 case DCERPC_PKT_BIND_ACK:
409 /* Client code never receives this kind of packets */
410 break;
413 case DCERPC_PKT_RESPONSE:
415 r = &pkt->u.response;
417 /* Here's where we deal with incoming sign/seal. */
418 ret = dcerpc_check_auth(cli->auth, pkt,
419 &r->stub_and_verifier,
420 DCERPC_RESPONSE_LENGTH,
421 pdu, &pad_len);
422 if (!NT_STATUS_IS_OK(ret)) {
423 return ret;
426 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
427 return NT_STATUS_BUFFER_TOO_SMALL;
430 /* Point the return values at the NDR data. */
431 rdata->data = r->stub_and_verifier.data;
433 if (pkt->auth_length) {
434 /* We've already done integer wrap tests in
435 * dcerpc_check_auth(). */
436 rdata->length = r->stub_and_verifier.length
437 - pad_len
438 - DCERPC_AUTH_TRAILER_LENGTH
439 - pkt->auth_length;
440 } else {
441 rdata->length = r->stub_and_verifier.length;
444 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
445 (long unsigned int)pdu->length,
446 (long unsigned int)rdata->length,
447 (unsigned int)pad_len));
450 * If this is the first reply, and the allocation hint is
451 * reasonable, try and set up the reply_pdu DATA_BLOB to the
452 * correct size.
455 if ((reply_pdu->length == 0) &&
456 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
457 if (!data_blob_realloc(mem_ctx, reply_pdu,
458 r->alloc_hint)) {
459 DEBUG(0, ("reply alloc hint %d too "
460 "large to allocate\n",
461 (int)r->alloc_hint));
462 return NT_STATUS_NO_MEMORY;
466 break;
468 case DCERPC_PKT_BIND_NAK:
469 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
470 rpccli_pipe_txt(talloc_tos(), cli)));
471 /* Use this for now... */
472 return NT_STATUS_NETWORK_ACCESS_DENIED;
474 case DCERPC_PKT_FAULT:
476 DEBUG(1, (__location__ ": RPC fault code %s received "
477 "from %s!\n",
478 dcerpc_errstr(talloc_tos(),
479 pkt->u.fault.status),
480 rpccli_pipe_txt(talloc_tos(), cli)));
482 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
484 default:
485 DEBUG(0, (__location__ "Unknown packet type %u received "
486 "from %s!\n",
487 (unsigned int)pkt->ptype,
488 rpccli_pipe_txt(talloc_tos(), cli)));
489 return NT_STATUS_RPC_PROTOCOL_ERROR;
492 if (pkt->ptype != expected_pkt_type) {
493 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
494 "RPC packet type - %u, not %u\n",
495 rpccli_pipe_txt(talloc_tos(), cli),
496 pkt->ptype, expected_pkt_type));
497 return NT_STATUS_RPC_PROTOCOL_ERROR;
500 if (pkt->call_id != call_id) {
501 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
502 "RPC call_id - %u, not %u\n",
503 rpccli_pipe_txt(talloc_tos(), cli),
504 pkt->call_id, call_id));
505 return NT_STATUS_RPC_PROTOCOL_ERROR;
508 /* Do this just before return - we don't want to modify any rpc header
509 data before now as we may have needed to do cryptographic actions on
510 it before. */
512 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
513 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
514 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
515 "fragment first/last ON.\n"));
516 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
519 return NT_STATUS_OK;
522 /****************************************************************************
523 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
524 ****************************************************************************/
526 struct cli_api_pipe_state {
527 struct tevent_context *ev;
528 struct rpc_cli_transport *transport;
529 uint8_t *rdata;
530 uint32_t rdata_len;
533 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
534 static void cli_api_pipe_write_done(struct tevent_req *subreq);
535 static void cli_api_pipe_read_done(struct tevent_req *subreq);
537 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
538 struct tevent_context *ev,
539 struct rpc_cli_transport *transport,
540 uint8_t *data, size_t data_len,
541 uint32_t max_rdata_len)
543 struct tevent_req *req, *subreq;
544 struct cli_api_pipe_state *state;
545 NTSTATUS status;
547 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
548 if (req == NULL) {
549 return NULL;
551 state->ev = ev;
552 state->transport = transport;
554 if (max_rdata_len < RPC_HEADER_LEN) {
556 * For a RPC reply we always need at least RPC_HEADER_LEN
557 * bytes. We check this here because we will receive
558 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
560 status = NT_STATUS_INVALID_PARAMETER;
561 goto post_status;
564 if (transport->trans_send != NULL) {
565 subreq = transport->trans_send(state, ev, data, data_len,
566 max_rdata_len, transport->priv);
567 if (subreq == NULL) {
568 goto fail;
570 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
571 return req;
575 * If the transport does not provide a "trans" routine, i.e. for
576 * example the ncacn_ip_tcp transport, do the write/read step here.
579 subreq = rpc_write_send(state, ev, transport, data, data_len);
580 if (subreq == NULL) {
581 goto fail;
583 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
584 return req;
586 post_status:
587 tevent_req_nterror(req, status);
588 return tevent_req_post(req, ev);
589 fail:
590 TALLOC_FREE(req);
591 return NULL;
594 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
596 struct tevent_req *req = tevent_req_callback_data(
597 subreq, struct tevent_req);
598 struct cli_api_pipe_state *state = tevent_req_data(
599 req, struct cli_api_pipe_state);
600 NTSTATUS status;
602 status = state->transport->trans_recv(subreq, state, &state->rdata,
603 &state->rdata_len);
604 TALLOC_FREE(subreq);
605 if (!NT_STATUS_IS_OK(status)) {
606 tevent_req_nterror(req, status);
607 return;
609 tevent_req_done(req);
612 static void cli_api_pipe_write_done(struct tevent_req *subreq)
614 struct tevent_req *req = tevent_req_callback_data(
615 subreq, struct tevent_req);
616 struct cli_api_pipe_state *state = tevent_req_data(
617 req, struct cli_api_pipe_state);
618 NTSTATUS status;
620 status = rpc_write_recv(subreq);
621 TALLOC_FREE(subreq);
622 if (!NT_STATUS_IS_OK(status)) {
623 tevent_req_nterror(req, status);
624 return;
627 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
628 if (tevent_req_nomem(state->rdata, req)) {
629 return;
633 * We don't need to use rpc_read_send here, the upper layer will cope
634 * with a short read, transport->trans_send could also return less
635 * than state->max_rdata_len.
637 subreq = state->transport->read_send(state, state->ev, state->rdata,
638 RPC_HEADER_LEN,
639 state->transport->priv);
640 if (tevent_req_nomem(subreq, req)) {
641 return;
643 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
646 static void cli_api_pipe_read_done(struct tevent_req *subreq)
648 struct tevent_req *req = tevent_req_callback_data(
649 subreq, struct tevent_req);
650 struct cli_api_pipe_state *state = tevent_req_data(
651 req, struct cli_api_pipe_state);
652 NTSTATUS status;
653 ssize_t received;
655 status = state->transport->read_recv(subreq, &received);
656 TALLOC_FREE(subreq);
657 if (!NT_STATUS_IS_OK(status)) {
658 tevent_req_nterror(req, status);
659 return;
661 state->rdata_len = received;
662 tevent_req_done(req);
665 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
666 uint8_t **prdata, uint32_t *prdata_len)
668 struct cli_api_pipe_state *state = tevent_req_data(
669 req, struct cli_api_pipe_state);
670 NTSTATUS status;
672 if (tevent_req_is_nterror(req, &status)) {
673 return status;
676 *prdata = talloc_move(mem_ctx, &state->rdata);
677 *prdata_len = state->rdata_len;
678 return NT_STATUS_OK;
681 /****************************************************************************
682 Send data on an rpc pipe via trans. The data must be the last
683 pdu fragment of an NDR data stream.
685 Receive response data from an rpc pipe, which may be large...
687 Read the first fragment: unfortunately have to use SMBtrans for the first
688 bit, then SMBreadX for subsequent bits.
690 If first fragment received also wasn't the last fragment, continue
691 getting fragments until we _do_ receive the last fragment.
693 Request/Response PDU's look like the following...
695 |<------------------PDU len----------------------------------------------->|
696 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
698 +------------+-----------------+-------------+---------------+-------------+
699 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
700 +------------+-----------------+-------------+---------------+-------------+
702 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
703 signing & sealing being negotiated.
705 ****************************************************************************/
707 struct rpc_api_pipe_state {
708 struct tevent_context *ev;
709 struct rpc_pipe_client *cli;
710 uint8_t expected_pkt_type;
711 uint32_t call_id;
713 DATA_BLOB incoming_frag;
714 struct ncacn_packet *pkt;
716 /* Incoming reply */
717 DATA_BLOB reply_pdu;
718 size_t reply_pdu_offset;
719 uint8_t endianess;
722 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
723 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
724 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
726 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
727 struct tevent_context *ev,
728 struct rpc_pipe_client *cli,
729 DATA_BLOB *data, /* Outgoing PDU */
730 uint8_t expected_pkt_type,
731 uint32_t call_id)
733 struct tevent_req *req, *subreq;
734 struct rpc_api_pipe_state *state;
735 uint16_t max_recv_frag;
736 NTSTATUS status;
738 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
739 if (req == NULL) {
740 return NULL;
742 state->ev = ev;
743 state->cli = cli;
744 state->expected_pkt_type = expected_pkt_type;
745 state->call_id = call_id;
746 state->endianess = DCERPC_DREP_LE;
749 * Ensure we're not sending too much.
751 if (data->length > cli->max_xmit_frag) {
752 status = NT_STATUS_INVALID_PARAMETER;
753 goto post_status;
756 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
758 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
759 subreq = rpc_write_send(state, ev, cli->transport,
760 data->data, data->length);
761 if (subreq == NULL) {
762 goto fail;
764 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
765 return req;
768 /* get the header first, then fetch the rest once we have
769 * the frag_length available */
770 max_recv_frag = RPC_HEADER_LEN;
772 subreq = cli_api_pipe_send(state, ev, cli->transport,
773 data->data, data->length, max_recv_frag);
774 if (subreq == NULL) {
775 goto fail;
777 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
778 return req;
780 post_status:
781 tevent_req_nterror(req, status);
782 return tevent_req_post(req, ev);
783 fail:
784 TALLOC_FREE(req);
785 return NULL;
788 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
790 struct tevent_req *req =
791 tevent_req_callback_data(subreq,
792 struct tevent_req);
793 NTSTATUS status;
795 status = rpc_write_recv(subreq);
796 TALLOC_FREE(subreq);
797 if (!NT_STATUS_IS_OK(status)) {
798 tevent_req_nterror(req, status);
799 return;
802 tevent_req_done(req);
805 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
807 struct tevent_req *req = tevent_req_callback_data(
808 subreq, struct tevent_req);
809 struct rpc_api_pipe_state *state = tevent_req_data(
810 req, struct rpc_api_pipe_state);
811 NTSTATUS status;
812 uint8_t *rdata = NULL;
813 uint32_t rdata_len = 0;
815 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
816 TALLOC_FREE(subreq);
817 if (!NT_STATUS_IS_OK(status)) {
818 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
819 tevent_req_nterror(req, status);
820 return;
823 if (rdata == NULL) {
824 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
825 rpccli_pipe_txt(talloc_tos(), state->cli)));
826 tevent_req_done(req);
827 return;
831 * Move data on state->incoming_frag.
833 state->incoming_frag.data = talloc_move(state, &rdata);
834 state->incoming_frag.length = rdata_len;
835 if (!state->incoming_frag.data) {
836 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
837 return;
840 /* Ensure we have enough data for a pdu. */
841 subreq = get_complete_frag_send(state, state->ev, state->cli,
842 &state->incoming_frag);
843 if (tevent_req_nomem(subreq, req)) {
844 return;
846 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
849 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
851 struct tevent_req *req = tevent_req_callback_data(
852 subreq, struct tevent_req);
853 struct rpc_api_pipe_state *state = tevent_req_data(
854 req, struct rpc_api_pipe_state);
855 NTSTATUS status;
856 DATA_BLOB rdata = data_blob_null;
858 status = get_complete_frag_recv(subreq);
859 TALLOC_FREE(subreq);
860 if (!NT_STATUS_IS_OK(status)) {
861 DEBUG(5, ("get_complete_frag failed: %s\n",
862 nt_errstr(status)));
863 tevent_req_nterror(req, status);
864 return;
867 state->pkt = talloc(state, struct ncacn_packet);
868 if (!state->pkt) {
869 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
870 return;
873 status = dcerpc_pull_ncacn_packet(state->pkt,
874 &state->incoming_frag,
875 state->pkt,
876 !state->endianess);
877 if (!NT_STATUS_IS_OK(status)) {
878 tevent_req_nterror(req, status);
879 return;
882 if (state->incoming_frag.length != state->pkt->frag_length) {
883 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
884 (unsigned int)state->incoming_frag.length,
885 (unsigned int)state->pkt->frag_length));
886 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
887 return;
890 status = cli_pipe_validate_current_pdu(state,
891 state->cli, state->pkt,
892 &state->incoming_frag,
893 state->expected_pkt_type,
894 state->call_id,
895 &rdata,
896 &state->reply_pdu);
898 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
899 (unsigned)state->incoming_frag.length,
900 (unsigned)state->reply_pdu_offset,
901 nt_errstr(status)));
903 if (!NT_STATUS_IS_OK(status)) {
904 tevent_req_nterror(req, status);
905 return;
908 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
909 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
911 * Set the data type correctly for big-endian data on the
912 * first packet.
914 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
915 "big-endian.\n",
916 rpccli_pipe_txt(talloc_tos(), state->cli)));
917 state->endianess = 0x00; /* BIG ENDIAN */
920 * Check endianness on subsequent packets.
922 if (state->endianess != state->pkt->drep[0]) {
923 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
924 "%s\n",
925 state->endianess?"little":"big",
926 state->pkt->drep[0]?"little":"big"));
927 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 return;
931 /* Now copy the data portion out of the pdu into rbuf. */
932 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
933 if (!data_blob_realloc(NULL, &state->reply_pdu,
934 state->reply_pdu_offset + rdata.length)) {
935 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
936 return;
940 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
941 rdata.data, rdata.length);
942 state->reply_pdu_offset += rdata.length;
944 /* reset state->incoming_frag, there is no need to free it,
945 * it will be reallocated to the right size the next time
946 * it is used */
947 state->incoming_frag.length = 0;
949 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
950 /* make sure the pdu length is right now that we
951 * have all the data available (alloc hint may
952 * have allocated more than was actually used) */
953 state->reply_pdu.length = state->reply_pdu_offset;
954 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
955 rpccli_pipe_txt(talloc_tos(), state->cli),
956 (unsigned)state->reply_pdu.length));
957 tevent_req_done(req);
958 return;
961 subreq = get_complete_frag_send(state, state->ev, state->cli,
962 &state->incoming_frag);
963 if (tevent_req_nomem(subreq, req)) {
964 return;
966 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
969 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
970 struct ncacn_packet **pkt,
971 DATA_BLOB *reply_pdu)
973 struct rpc_api_pipe_state *state = tevent_req_data(
974 req, struct rpc_api_pipe_state);
975 NTSTATUS status;
977 if (tevent_req_is_nterror(req, &status)) {
978 return status;
981 /* return data to caller and assign it ownership of memory */
982 if (reply_pdu) {
983 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
984 reply_pdu->length = state->reply_pdu.length;
985 state->reply_pdu.length = 0;
986 } else {
987 data_blob_free(&state->reply_pdu);
990 if (pkt) {
991 *pkt = talloc_steal(mem_ctx, state->pkt);
994 return NT_STATUS_OK;
997 /*******************************************************************
998 Creates NTLMSSP auth bind.
999 ********************************************************************/
1001 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1002 TALLOC_CTX *mem_ctx,
1003 DATA_BLOB *auth_token,
1004 bool *client_hdr_signing)
1006 struct gensec_security *gensec_security;
1007 DATA_BLOB null_blob = data_blob_null;
1008 NTSTATUS status;
1010 gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
1011 struct gensec_security);
1013 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1014 status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
1016 if (!NT_STATUS_IS_OK(status) &&
1017 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1019 return status;
1022 if (client_hdr_signing == NULL) {
1023 return status;
1026 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1027 *client_hdr_signing = false;
1028 return status;
1031 *client_hdr_signing = gensec_have_feature(gensec_security,
1032 GENSEC_FEATURE_SIGN_PKT_HEADER);
1034 return status;
1037 /*******************************************************************
1038 Creates the internals of a DCE/RPC bind request or alter context PDU.
1039 ********************************************************************/
1041 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1042 enum dcerpc_pkt_type ptype,
1043 uint32 rpc_call_id,
1044 const struct ndr_syntax_id *abstract,
1045 const struct ndr_syntax_id *transfer,
1046 const DATA_BLOB *auth_info,
1047 bool client_hdr_signing,
1048 DATA_BLOB *blob)
1050 uint16 auth_len = auth_info->length;
1051 NTSTATUS status;
1052 union dcerpc_payload u;
1053 struct dcerpc_ctx_list ctx_list;
1054 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1056 if (auth_len) {
1057 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1060 if (client_hdr_signing) {
1061 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1064 ctx_list.context_id = 0;
1065 ctx_list.num_transfer_syntaxes = 1;
1066 ctx_list.abstract_syntax = *abstract;
1067 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1069 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1070 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1071 u.bind.assoc_group_id = 0x0;
1072 u.bind.num_contexts = 1;
1073 u.bind.ctx_list = &ctx_list;
1074 u.bind.auth_info = *auth_info;
1076 status = dcerpc_push_ncacn_packet(mem_ctx,
1077 ptype, pfc_flags,
1078 auth_len,
1079 rpc_call_id,
1081 blob);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1084 return status;
1087 return NT_STATUS_OK;
1090 /*******************************************************************
1091 Creates a DCE/RPC bind request.
1092 ********************************************************************/
1094 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1095 struct rpc_pipe_client *cli,
1096 struct pipe_auth_data *auth,
1097 uint32 rpc_call_id,
1098 const struct ndr_syntax_id *abstract,
1099 const struct ndr_syntax_id *transfer,
1100 DATA_BLOB *rpc_out)
1102 DATA_BLOB auth_token = data_blob_null;
1103 DATA_BLOB auth_info = data_blob_null;
1104 NTSTATUS ret = NT_STATUS_OK;
1106 switch (auth->auth_type) {
1107 case DCERPC_AUTH_TYPE_SCHANNEL:
1108 case DCERPC_AUTH_TYPE_NTLMSSP:
1109 case DCERPC_AUTH_TYPE_KRB5:
1110 case DCERPC_AUTH_TYPE_SPNEGO:
1111 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1112 &auth_token,
1113 &auth->client_hdr_signing);
1115 if (!NT_STATUS_IS_OK(ret) &&
1116 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1117 return ret;
1119 break;
1121 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1122 auth_token = data_blob_talloc(mem_ctx,
1123 "NCALRPC_AUTH_TOKEN",
1124 18);
1125 break;
1127 case DCERPC_AUTH_TYPE_NONE:
1128 break;
1130 default:
1131 /* "Can't" happen. */
1132 return NT_STATUS_INVALID_INFO_CLASS;
1135 if (auth_token.length != 0) {
1136 ret = dcerpc_push_dcerpc_auth(cli,
1137 auth->auth_type,
1138 auth->auth_level,
1139 0, /* auth_pad_length */
1140 1, /* auth_context_id */
1141 &auth_token,
1142 &auth_info);
1143 if (!NT_STATUS_IS_OK(ret)) {
1144 return ret;
1146 data_blob_free(&auth_token);
1149 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1150 DCERPC_PKT_BIND,
1151 rpc_call_id,
1152 abstract,
1153 transfer,
1154 &auth_info,
1155 auth->client_hdr_signing,
1156 rpc_out);
1157 return ret;
1160 /*******************************************************************
1161 External interface.
1162 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1163 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1164 and deals with signing/sealing details.
1165 ********************************************************************/
1167 struct rpc_api_pipe_req_state {
1168 struct tevent_context *ev;
1169 struct rpc_pipe_client *cli;
1170 uint8_t op_num;
1171 uint32_t call_id;
1172 const DATA_BLOB *req_data;
1173 uint32_t req_data_sent;
1174 DATA_BLOB req_trailer;
1175 uint32_t req_trailer_sent;
1176 bool verify_bitmask1;
1177 bool verify_pcontext;
1178 DATA_BLOB rpc_out;
1179 DATA_BLOB reply_pdu;
1182 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1183 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1184 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1185 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1186 bool *is_last_frag);
1188 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1189 struct tevent_context *ev,
1190 struct rpc_pipe_client *cli,
1191 uint8_t op_num,
1192 const DATA_BLOB *req_data)
1194 struct tevent_req *req, *subreq;
1195 struct rpc_api_pipe_req_state *state;
1196 NTSTATUS status;
1197 bool is_last_frag;
1199 req = tevent_req_create(mem_ctx, &state,
1200 struct rpc_api_pipe_req_state);
1201 if (req == NULL) {
1202 return NULL;
1204 state->ev = ev;
1205 state->cli = cli;
1206 state->op_num = op_num;
1207 state->req_data = req_data;
1208 state->req_data_sent = 0;
1209 state->call_id = get_rpc_call_id();
1210 state->reply_pdu = data_blob_null;
1211 state->rpc_out = data_blob_null;
1213 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1214 + RPC_MAX_SIGN_SIZE) {
1215 /* Server is screwed up ! */
1216 status = NT_STATUS_INVALID_PARAMETER;
1217 goto post_status;
1220 status = prepare_verification_trailer(state);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 goto post_status;
1225 status = prepare_next_frag(state, &is_last_frag);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 goto post_status;
1230 if (is_last_frag) {
1231 subreq = rpc_api_pipe_send(state, ev, state->cli,
1232 &state->rpc_out,
1233 DCERPC_PKT_RESPONSE,
1234 state->call_id);
1235 if (subreq == NULL) {
1236 goto fail;
1238 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1239 } else {
1240 subreq = rpc_write_send(state, ev, cli->transport,
1241 state->rpc_out.data,
1242 state->rpc_out.length);
1243 if (subreq == NULL) {
1244 goto fail;
1246 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1247 req);
1249 return req;
1251 post_status:
1252 tevent_req_nterror(req, status);
1253 return tevent_req_post(req, ev);
1254 fail:
1255 TALLOC_FREE(req);
1256 return NULL;
1259 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1261 struct pipe_auth_data *a = state->cli->auth;
1262 struct dcerpc_sec_verification_trailer *t;
1263 struct dcerpc_sec_vt *c = NULL;
1264 struct ndr_push *ndr = NULL;
1265 enum ndr_err_code ndr_err;
1266 size_t align = 0;
1267 size_t pad = 0;
1269 if (a == NULL) {
1270 return NT_STATUS_OK;
1273 if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1274 return NT_STATUS_OK;
1277 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1278 if (t == NULL) {
1279 return NT_STATUS_NO_MEMORY;
1282 if (!a->verified_bitmask1) {
1283 t->commands = talloc_realloc(t, t->commands,
1284 struct dcerpc_sec_vt,
1285 t->count.count + 1);
1286 if (t->commands == NULL) {
1287 return NT_STATUS_NO_MEMORY;
1289 c = &t->commands[t->count.count++];
1290 ZERO_STRUCTP(c);
1292 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1293 if (a->client_hdr_signing) {
1294 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1296 state->verify_bitmask1 = true;
1299 if (!state->cli->verified_pcontext) {
1300 t->commands = talloc_realloc(t, t->commands,
1301 struct dcerpc_sec_vt,
1302 t->count.count + 1);
1303 if (t->commands == NULL) {
1304 return NT_STATUS_NO_MEMORY;
1306 c = &t->commands[t->count.count++];
1307 ZERO_STRUCTP(c);
1309 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1310 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1311 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1313 state->verify_pcontext = true;
1316 if (!a->hdr_signing) {
1317 t->commands = talloc_realloc(t, t->commands,
1318 struct dcerpc_sec_vt,
1319 t->count.count + 1);
1320 if (t->commands == NULL) {
1321 return NT_STATUS_NO_MEMORY;
1323 c = &t->commands[t->count.count++];
1324 ZERO_STRUCTP(c);
1326 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1327 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1328 c->u.header2.drep[0] = DCERPC_DREP_LE;
1329 c->u.header2.drep[1] = 0;
1330 c->u.header2.drep[2] = 0;
1331 c->u.header2.drep[3] = 0;
1332 c->u.header2.call_id = state->call_id;
1333 c->u.header2.context_id = 0;
1334 c->u.header2.opnum = state->op_num;
1337 if (t->count.count == 0) {
1338 TALLOC_FREE(t);
1339 return NT_STATUS_OK;
1342 c = &t->commands[t->count.count - 1];
1343 c->command |= DCERPC_SEC_VT_COMMAND_END;
1345 if (DEBUGLEVEL >= 10) {
1346 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1349 ndr = ndr_push_init_ctx(state);
1350 if (ndr == NULL) {
1351 return NT_STATUS_NO_MEMORY;
1354 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1355 NDR_SCALARS | NDR_BUFFERS,
1357 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1358 return ndr_map_error2ntstatus(ndr_err);
1360 state->req_trailer = ndr_push_blob(ndr);
1362 align = state->req_data->length & 0x3;
1363 if (align > 0) {
1364 pad = 4 - align;
1366 if (pad > 0) {
1367 bool ok;
1368 uint8_t *p;
1369 const uint8_t zeros[4] = { 0, };
1371 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1372 if (!ok) {
1373 return NT_STATUS_NO_MEMORY;
1376 /* move the padding to the start */
1377 p = state->req_trailer.data;
1378 memmove(p + pad, p, state->req_trailer.length - pad);
1379 memset(p, 0, pad);
1382 return NT_STATUS_OK;
1385 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1386 bool *is_last_frag)
1388 size_t auth_len;
1389 size_t frag_len;
1390 uint8_t flags = 0;
1391 size_t pad_len;
1392 size_t data_left;
1393 size_t data_thistime;
1394 size_t trailer_left;
1395 size_t trailer_thistime = 0;
1396 size_t total_left;
1397 size_t total_thistime;
1398 NTSTATUS status;
1399 bool ok;
1400 union dcerpc_payload u;
1402 data_left = state->req_data->length - state->req_data_sent;
1403 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1404 total_left = data_left + trailer_left;
1405 if ((total_left < data_left) || (total_left < trailer_left)) {
1407 * overflow
1409 return NT_STATUS_INVALID_PARAMETER_MIX;
1412 status = dcerpc_guess_sizes(state->cli->auth,
1413 DCERPC_REQUEST_LENGTH, total_left,
1414 state->cli->max_xmit_frag,
1415 CLIENT_NDR_PADDING_SIZE,
1416 &total_thistime,
1417 &frag_len, &auth_len, &pad_len);
1418 if (!NT_STATUS_IS_OK(status)) {
1419 return status;
1422 if (state->req_data_sent == 0) {
1423 flags = DCERPC_PFC_FLAG_FIRST;
1426 if (total_thistime == total_left) {
1427 flags |= DCERPC_PFC_FLAG_LAST;
1430 data_thistime = MIN(total_thistime, data_left);
1431 if (data_thistime < total_thistime) {
1432 trailer_thistime = total_thistime - data_thistime;
1435 data_blob_free(&state->rpc_out);
1437 ZERO_STRUCT(u.request);
1439 u.request.alloc_hint = total_left;
1440 u.request.context_id = 0;
1441 u.request.opnum = state->op_num;
1443 status = dcerpc_push_ncacn_packet(state,
1444 DCERPC_PKT_REQUEST,
1445 flags,
1446 auth_len,
1447 state->call_id,
1449 &state->rpc_out);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return status;
1454 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1455 * compute it right for requests because the auth trailer is missing
1456 * at this stage */
1457 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1459 if (data_thistime > 0) {
1460 /* Copy in the data. */
1461 ok = data_blob_append(NULL, &state->rpc_out,
1462 state->req_data->data + state->req_data_sent,
1463 data_thistime);
1464 if (!ok) {
1465 return NT_STATUS_NO_MEMORY;
1467 state->req_data_sent += data_thistime;
1470 if (trailer_thistime > 0) {
1471 /* Copy in the verification trailer. */
1472 ok = data_blob_append(NULL, &state->rpc_out,
1473 state->req_trailer.data + state->req_trailer_sent,
1474 trailer_thistime);
1475 if (!ok) {
1476 return NT_STATUS_NO_MEMORY;
1478 state->req_trailer_sent += trailer_thistime;
1481 switch (state->cli->auth->auth_level) {
1482 case DCERPC_AUTH_LEVEL_NONE:
1483 case DCERPC_AUTH_LEVEL_CONNECT:
1484 case DCERPC_AUTH_LEVEL_PACKET:
1485 break;
1486 case DCERPC_AUTH_LEVEL_INTEGRITY:
1487 case DCERPC_AUTH_LEVEL_PRIVACY:
1488 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1489 &state->rpc_out);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 return status;
1493 break;
1494 default:
1495 return NT_STATUS_INVALID_PARAMETER;
1498 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1500 return status;
1503 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1505 struct tevent_req *req = tevent_req_callback_data(
1506 subreq, struct tevent_req);
1507 struct rpc_api_pipe_req_state *state = tevent_req_data(
1508 req, struct rpc_api_pipe_req_state);
1509 NTSTATUS status;
1510 bool is_last_frag;
1512 status = rpc_write_recv(subreq);
1513 TALLOC_FREE(subreq);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 tevent_req_nterror(req, status);
1516 return;
1519 status = prepare_next_frag(state, &is_last_frag);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 tevent_req_nterror(req, status);
1522 return;
1525 if (is_last_frag) {
1526 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1527 &state->rpc_out,
1528 DCERPC_PKT_RESPONSE,
1529 state->call_id);
1530 if (tevent_req_nomem(subreq, req)) {
1531 return;
1533 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1534 } else {
1535 subreq = rpc_write_send(state, state->ev,
1536 state->cli->transport,
1537 state->rpc_out.data,
1538 state->rpc_out.length);
1539 if (tevent_req_nomem(subreq, req)) {
1540 return;
1542 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1543 req);
1547 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1549 struct tevent_req *req = tevent_req_callback_data(
1550 subreq, struct tevent_req);
1551 struct rpc_api_pipe_req_state *state = tevent_req_data(
1552 req, struct rpc_api_pipe_req_state);
1553 NTSTATUS status;
1555 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1556 TALLOC_FREE(subreq);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 tevent_req_nterror(req, status);
1559 return;
1562 if (state->cli->auth == NULL) {
1563 tevent_req_done(req);
1564 return;
1567 if (state->verify_bitmask1) {
1568 state->cli->auth->verified_bitmask1 = true;
1571 if (state->verify_pcontext) {
1572 state->cli->verified_pcontext = true;
1575 tevent_req_done(req);
1578 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1579 DATA_BLOB *reply_pdu)
1581 struct rpc_api_pipe_req_state *state = tevent_req_data(
1582 req, struct rpc_api_pipe_req_state);
1583 NTSTATUS status;
1585 if (tevent_req_is_nterror(req, &status)) {
1587 * We always have to initialize to reply pdu, even if there is
1588 * none. The rpccli_* caller routines expect this.
1590 *reply_pdu = data_blob_null;
1591 return status;
1594 /* return data to caller and assign it ownership of memory */
1595 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1596 reply_pdu->length = state->reply_pdu.length;
1597 state->reply_pdu.length = 0;
1599 return NT_STATUS_OK;
1602 /****************************************************************************
1603 Check the rpc bind acknowledge response.
1604 ****************************************************************************/
1606 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1607 const struct ndr_syntax_id *transfer)
1609 struct dcerpc_ack_ctx ctx;
1611 if (r->secondary_address_size == 0) {
1612 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1615 if (r->num_results < 1 || !r->ctx_list) {
1616 return false;
1619 ctx = r->ctx_list[0];
1621 /* check the transfer syntax */
1622 if ((ctx.syntax.if_version != transfer->if_version) ||
1623 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1624 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1625 return False;
1628 if (r->num_results != 0x1 || ctx.result != 0) {
1629 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1630 r->num_results, ctx.reason.value));
1633 DEBUG(5,("check_bind_response: accepted!\n"));
1634 return True;
1637 /*******************************************************************
1638 Creates a DCE/RPC bind authentication response.
1639 This is the packet that is sent back to the server once we
1640 have received a BIND-ACK, to finish the third leg of
1641 the authentication handshake.
1642 ********************************************************************/
1644 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1645 struct rpc_pipe_client *cli,
1646 uint32 rpc_call_id,
1647 enum dcerpc_AuthType auth_type,
1648 enum dcerpc_AuthLevel auth_level,
1649 DATA_BLOB *pauth_blob,
1650 DATA_BLOB *rpc_out)
1652 NTSTATUS status;
1653 union dcerpc_payload u;
1655 u.auth3._pad = 0;
1657 status = dcerpc_push_dcerpc_auth(mem_ctx,
1658 auth_type,
1659 auth_level,
1660 0, /* auth_pad_length */
1661 1, /* auth_context_id */
1662 pauth_blob,
1663 &u.auth3.auth_info);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 return status;
1668 status = dcerpc_push_ncacn_packet(mem_ctx,
1669 DCERPC_PKT_AUTH3,
1670 DCERPC_PFC_FLAG_FIRST |
1671 DCERPC_PFC_FLAG_LAST,
1672 pauth_blob->length,
1673 rpc_call_id,
1675 rpc_out);
1676 data_blob_free(&u.auth3.auth_info);
1677 if (!NT_STATUS_IS_OK(status)) {
1678 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1679 return status;
1682 return NT_STATUS_OK;
1685 /*******************************************************************
1686 Creates a DCE/RPC bind alter context authentication request which
1687 may contain a spnego auth blobl
1688 ********************************************************************/
1690 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1691 enum dcerpc_AuthType auth_type,
1692 enum dcerpc_AuthLevel auth_level,
1693 uint32 rpc_call_id,
1694 const struct ndr_syntax_id *abstract,
1695 const struct ndr_syntax_id *transfer,
1696 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1697 DATA_BLOB *rpc_out)
1699 DATA_BLOB auth_info;
1700 NTSTATUS status;
1702 status = dcerpc_push_dcerpc_auth(mem_ctx,
1703 auth_type,
1704 auth_level,
1705 0, /* auth_pad_length */
1706 1, /* auth_context_id */
1707 pauth_blob,
1708 &auth_info);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 return status;
1713 status = create_bind_or_alt_ctx_internal(mem_ctx,
1714 DCERPC_PKT_ALTER,
1715 rpc_call_id,
1716 abstract,
1717 transfer,
1718 &auth_info,
1719 false, /* client_hdr_signing */
1720 rpc_out);
1721 data_blob_free(&auth_info);
1722 return status;
1725 /****************************************************************************
1726 Do an rpc bind.
1727 ****************************************************************************/
1729 struct rpc_pipe_bind_state {
1730 struct tevent_context *ev;
1731 struct rpc_pipe_client *cli;
1732 DATA_BLOB rpc_out;
1733 bool auth3;
1734 uint32_t rpc_call_id;
1737 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1738 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1739 struct rpc_pipe_bind_state *state,
1740 DATA_BLOB *credentials);
1741 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1742 struct rpc_pipe_bind_state *state,
1743 DATA_BLOB *credentials);
1745 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1746 struct tevent_context *ev,
1747 struct rpc_pipe_client *cli,
1748 struct pipe_auth_data *auth)
1750 struct tevent_req *req, *subreq;
1751 struct rpc_pipe_bind_state *state;
1752 NTSTATUS status;
1754 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1755 if (req == NULL) {
1756 return NULL;
1759 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1760 rpccli_pipe_txt(talloc_tos(), cli),
1761 (unsigned int)auth->auth_type,
1762 (unsigned int)auth->auth_level ));
1764 state->ev = ev;
1765 state->cli = cli;
1766 state->rpc_call_id = get_rpc_call_id();
1768 cli->auth = talloc_move(cli, &auth);
1770 /* Marshall the outgoing data. */
1771 status = create_rpc_bind_req(state, cli,
1772 cli->auth,
1773 state->rpc_call_id,
1774 &cli->abstract_syntax,
1775 &cli->transfer_syntax,
1776 &state->rpc_out);
1778 if (!NT_STATUS_IS_OK(status) &&
1779 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1780 goto post_status;
1783 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1784 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1785 if (subreq == NULL) {
1786 goto fail;
1788 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1789 return req;
1791 post_status:
1792 tevent_req_nterror(req, status);
1793 return tevent_req_post(req, ev);
1794 fail:
1795 TALLOC_FREE(req);
1796 return NULL;
1799 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1801 struct tevent_req *req = tevent_req_callback_data(
1802 subreq, struct tevent_req);
1803 struct rpc_pipe_bind_state *state = tevent_req_data(
1804 req, struct rpc_pipe_bind_state);
1805 struct pipe_auth_data *pauth = state->cli->auth;
1806 struct gensec_security *gensec_security;
1807 struct ncacn_packet *pkt = NULL;
1808 struct dcerpc_auth auth;
1809 DATA_BLOB auth_token = data_blob_null;
1810 NTSTATUS status;
1812 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1813 TALLOC_FREE(subreq);
1814 if (!NT_STATUS_IS_OK(status)) {
1815 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1816 rpccli_pipe_txt(talloc_tos(), state->cli),
1817 nt_errstr(status)));
1818 tevent_req_nterror(req, status);
1819 return;
1822 if (state->auth3) {
1823 tevent_req_done(req);
1824 return;
1827 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1828 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1829 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1830 return;
1833 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1834 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1836 switch(pauth->auth_type) {
1838 case DCERPC_AUTH_TYPE_NONE:
1839 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1840 /* Bind complete. */
1841 tevent_req_done(req);
1842 return;
1844 case DCERPC_AUTH_TYPE_SCHANNEL:
1845 case DCERPC_AUTH_TYPE_NTLMSSP:
1846 case DCERPC_AUTH_TYPE_SPNEGO:
1847 case DCERPC_AUTH_TYPE_KRB5:
1848 /* Paranoid lenght checks */
1849 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1850 + pkt->auth_length) {
1851 tevent_req_nterror(req,
1852 NT_STATUS_INFO_LENGTH_MISMATCH);
1853 return;
1855 /* get auth credentials */
1856 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1857 &pkt->u.bind_ack.auth_info,
1858 &auth, false);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1861 nt_errstr(status)));
1862 tevent_req_nterror(req, status);
1863 return;
1865 break;
1867 default:
1868 goto err_out;
1872 * For authenticated binds we may need to do 3 or 4 leg binds.
1875 switch(pauth->auth_type) {
1877 case DCERPC_AUTH_TYPE_NONE:
1878 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1879 /* Bind complete. */
1880 tevent_req_done(req);
1881 return;
1883 case DCERPC_AUTH_TYPE_SCHANNEL:
1884 case DCERPC_AUTH_TYPE_NTLMSSP:
1885 case DCERPC_AUTH_TYPE_KRB5:
1886 case DCERPC_AUTH_TYPE_SPNEGO:
1887 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1888 struct gensec_security);
1890 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1891 if (pauth->client_hdr_signing) {
1892 pauth->hdr_signing = true;
1893 gensec_want_feature(gensec_security,
1894 GENSEC_FEATURE_SIGN_PKT_HEADER);
1898 status = gensec_update(gensec_security, state, NULL,
1899 auth.credentials, &auth_token);
1900 if (NT_STATUS_EQUAL(status,
1901 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1902 status = rpc_bind_next_send(req, state,
1903 &auth_token);
1904 } else if (NT_STATUS_IS_OK(status)) {
1905 if (auth_token.length == 0) {
1906 /* Bind complete. */
1907 tevent_req_done(req);
1908 return;
1910 status = rpc_bind_finish_send(req, state,
1911 &auth_token);
1913 break;
1915 default:
1916 goto err_out;
1919 if (!NT_STATUS_IS_OK(status)) {
1920 tevent_req_nterror(req, status);
1922 return;
1924 err_out:
1925 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1926 (unsigned int)state->cli->auth->auth_type));
1927 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1930 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1931 struct rpc_pipe_bind_state *state,
1932 DATA_BLOB *auth_token)
1934 struct pipe_auth_data *auth = state->cli->auth;
1935 struct tevent_req *subreq;
1936 NTSTATUS status;
1938 /* Now prepare the alter context pdu. */
1939 data_blob_free(&state->rpc_out);
1941 status = create_rpc_alter_context(state,
1942 auth->auth_type,
1943 auth->auth_level,
1944 state->rpc_call_id,
1945 &state->cli->abstract_syntax,
1946 &state->cli->transfer_syntax,
1947 auth_token,
1948 &state->rpc_out);
1949 if (!NT_STATUS_IS_OK(status)) {
1950 return status;
1953 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1954 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
1955 state->rpc_call_id);
1956 if (subreq == NULL) {
1957 return NT_STATUS_NO_MEMORY;
1959 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1960 return NT_STATUS_OK;
1963 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1964 struct rpc_pipe_bind_state *state,
1965 DATA_BLOB *auth_token)
1967 struct pipe_auth_data *auth = state->cli->auth;
1968 struct tevent_req *subreq;
1969 NTSTATUS status;
1971 state->auth3 = true;
1973 /* Now prepare the auth3 context pdu. */
1974 data_blob_free(&state->rpc_out);
1976 status = create_rpc_bind_auth3(state, state->cli,
1977 state->rpc_call_id,
1978 auth->auth_type,
1979 auth->auth_level,
1980 auth_token,
1981 &state->rpc_out);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 return status;
1986 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1987 &state->rpc_out, DCERPC_PKT_AUTH3,
1988 state->rpc_call_id);
1989 if (subreq == NULL) {
1990 return NT_STATUS_NO_MEMORY;
1992 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1993 return NT_STATUS_OK;
1996 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1998 return tevent_req_simple_recv_ntstatus(req);
2001 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2002 struct pipe_auth_data *auth)
2004 TALLOC_CTX *frame = talloc_stackframe();
2005 struct tevent_context *ev;
2006 struct tevent_req *req;
2007 NTSTATUS status = NT_STATUS_OK;
2009 ev = samba_tevent_context_init(frame);
2010 if (ev == NULL) {
2011 status = NT_STATUS_NO_MEMORY;
2012 goto fail;
2015 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2016 if (req == NULL) {
2017 status = NT_STATUS_NO_MEMORY;
2018 goto fail;
2021 if (!tevent_req_poll(req, ev)) {
2022 status = map_nt_error_from_unix(errno);
2023 goto fail;
2026 status = rpc_pipe_bind_recv(req);
2027 fail:
2028 TALLOC_FREE(frame);
2029 return status;
2032 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2034 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2035 unsigned int timeout)
2037 unsigned int old;
2039 if (rpc_cli->transport == NULL) {
2040 return RPCCLI_DEFAULT_TIMEOUT;
2043 if (rpc_cli->transport->set_timeout == NULL) {
2044 return RPCCLI_DEFAULT_TIMEOUT;
2047 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2048 if (old == 0) {
2049 return RPCCLI_DEFAULT_TIMEOUT;
2052 return old;
2055 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2057 if (rpc_cli == NULL) {
2058 return false;
2061 if (rpc_cli->transport == NULL) {
2062 return false;
2065 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2068 struct rpccli_bh_state {
2069 struct rpc_pipe_client *rpc_cli;
2072 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2074 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2075 struct rpccli_bh_state);
2077 return rpccli_is_connected(hs->rpc_cli);
2080 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2081 uint32_t timeout)
2083 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2084 struct rpccli_bh_state);
2086 return rpccli_set_timeout(hs->rpc_cli, timeout);
2089 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2090 enum dcerpc_AuthType *auth_type,
2091 enum dcerpc_AuthLevel *auth_level)
2093 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2094 struct rpccli_bh_state);
2096 if (hs->rpc_cli == NULL) {
2097 return;
2100 if (hs->rpc_cli->auth == NULL) {
2101 return;
2104 *auth_type = hs->rpc_cli->auth->auth_type;
2105 *auth_level = hs->rpc_cli->auth->auth_level;
2108 struct rpccli_bh_raw_call_state {
2109 DATA_BLOB in_data;
2110 DATA_BLOB out_data;
2111 uint32_t out_flags;
2114 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2116 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2117 struct tevent_context *ev,
2118 struct dcerpc_binding_handle *h,
2119 const struct GUID *object,
2120 uint32_t opnum,
2121 uint32_t in_flags,
2122 const uint8_t *in_data,
2123 size_t in_length)
2125 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2126 struct rpccli_bh_state);
2127 struct tevent_req *req;
2128 struct rpccli_bh_raw_call_state *state;
2129 bool ok;
2130 struct tevent_req *subreq;
2132 req = tevent_req_create(mem_ctx, &state,
2133 struct rpccli_bh_raw_call_state);
2134 if (req == NULL) {
2135 return NULL;
2137 state->in_data.data = discard_const_p(uint8_t, in_data);
2138 state->in_data.length = in_length;
2140 ok = rpccli_bh_is_connected(h);
2141 if (!ok) {
2142 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2143 return tevent_req_post(req, ev);
2146 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2147 opnum, &state->in_data);
2148 if (tevent_req_nomem(subreq, req)) {
2149 return tevent_req_post(req, ev);
2151 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2153 return req;
2156 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2158 struct tevent_req *req =
2159 tevent_req_callback_data(subreq,
2160 struct tevent_req);
2161 struct rpccli_bh_raw_call_state *state =
2162 tevent_req_data(req,
2163 struct rpccli_bh_raw_call_state);
2164 NTSTATUS status;
2166 state->out_flags = 0;
2168 /* TODO: support bigendian responses */
2170 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2171 TALLOC_FREE(subreq);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 tevent_req_nterror(req, status);
2174 return;
2177 tevent_req_done(req);
2180 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2181 TALLOC_CTX *mem_ctx,
2182 uint8_t **out_data,
2183 size_t *out_length,
2184 uint32_t *out_flags)
2186 struct rpccli_bh_raw_call_state *state =
2187 tevent_req_data(req,
2188 struct rpccli_bh_raw_call_state);
2189 NTSTATUS status;
2191 if (tevent_req_is_nterror(req, &status)) {
2192 tevent_req_received(req);
2193 return status;
2196 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2197 *out_length = state->out_data.length;
2198 *out_flags = state->out_flags;
2199 tevent_req_received(req);
2200 return NT_STATUS_OK;
2203 struct rpccli_bh_disconnect_state {
2204 uint8_t _dummy;
2207 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2208 struct tevent_context *ev,
2209 struct dcerpc_binding_handle *h)
2211 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2212 struct rpccli_bh_state);
2213 struct tevent_req *req;
2214 struct rpccli_bh_disconnect_state *state;
2215 bool ok;
2217 req = tevent_req_create(mem_ctx, &state,
2218 struct rpccli_bh_disconnect_state);
2219 if (req == NULL) {
2220 return NULL;
2223 ok = rpccli_bh_is_connected(h);
2224 if (!ok) {
2225 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2226 return tevent_req_post(req, ev);
2230 * TODO: do a real async disconnect ...
2232 * For now the caller needs to free rpc_cli
2234 hs->rpc_cli = NULL;
2236 tevent_req_done(req);
2237 return tevent_req_post(req, ev);
2240 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2242 NTSTATUS status;
2244 if (tevent_req_is_nterror(req, &status)) {
2245 tevent_req_received(req);
2246 return status;
2249 tevent_req_received(req);
2250 return NT_STATUS_OK;
2253 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2255 return true;
2258 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2259 int ndr_flags,
2260 const void *_struct_ptr,
2261 const struct ndr_interface_call *call)
2263 void *struct_ptr = discard_const(_struct_ptr);
2265 if (DEBUGLEVEL < 10) {
2266 return;
2269 if (ndr_flags & NDR_IN) {
2270 ndr_print_function_debug(call->ndr_print,
2271 call->name,
2272 ndr_flags,
2273 struct_ptr);
2275 if (ndr_flags & NDR_OUT) {
2276 ndr_print_function_debug(call->ndr_print,
2277 call->name,
2278 ndr_flags,
2279 struct_ptr);
2283 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2284 .name = "rpccli",
2285 .is_connected = rpccli_bh_is_connected,
2286 .set_timeout = rpccli_bh_set_timeout,
2287 .auth_info = rpccli_bh_auth_info,
2288 .raw_call_send = rpccli_bh_raw_call_send,
2289 .raw_call_recv = rpccli_bh_raw_call_recv,
2290 .disconnect_send = rpccli_bh_disconnect_send,
2291 .disconnect_recv = rpccli_bh_disconnect_recv,
2293 .ref_alloc = rpccli_bh_ref_alloc,
2294 .do_ndr_print = rpccli_bh_do_ndr_print,
2297 /* initialise a rpc_pipe_client binding handle */
2298 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2299 const struct GUID *object,
2300 const struct ndr_interface_table *table)
2302 struct dcerpc_binding_handle *h;
2303 struct rpccli_bh_state *hs;
2305 h = dcerpc_binding_handle_create(c,
2306 &rpccli_bh_ops,
2307 object,
2308 table,
2309 &hs,
2310 struct rpccli_bh_state,
2311 __location__);
2312 if (h == NULL) {
2313 return NULL;
2315 hs->rpc_cli = c;
2317 return h;
2320 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2321 struct pipe_auth_data **presult)
2323 struct pipe_auth_data *result;
2325 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2326 if (result == NULL) {
2327 return NT_STATUS_NO_MEMORY;
2330 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2331 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2333 result->user_name = talloc_strdup(result, "");
2334 result->domain = talloc_strdup(result, "");
2335 if ((result->user_name == NULL) || (result->domain == NULL)) {
2336 TALLOC_FREE(result);
2337 return NT_STATUS_NO_MEMORY;
2340 *presult = result;
2341 return NT_STATUS_OK;
2344 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2345 struct pipe_auth_data **presult)
2347 struct pipe_auth_data *result;
2349 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2350 if (result == NULL) {
2351 return NT_STATUS_NO_MEMORY;
2354 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2355 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2357 result->user_name = talloc_strdup(result, "");
2358 result->domain = talloc_strdup(result, "");
2359 if ((result->user_name == NULL) || (result->domain == NULL)) {
2360 TALLOC_FREE(result);
2361 return NT_STATUS_NO_MEMORY;
2364 *presult = result;
2365 return NT_STATUS_OK;
2368 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2369 enum dcerpc_AuthType auth_type,
2370 enum dcerpc_AuthLevel auth_level,
2371 const char *server,
2372 const char *target_service,
2373 const char *domain,
2374 const char *username,
2375 const char *password,
2376 enum credentials_use_kerberos use_kerberos,
2377 struct netlogon_creds_CredentialState *creds,
2378 struct pipe_auth_data **presult)
2380 struct auth_generic_state *auth_generic_ctx;
2381 struct pipe_auth_data *result;
2382 NTSTATUS status;
2384 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2385 if (result == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2389 result->auth_type = auth_type;
2390 result->auth_level = auth_level;
2392 result->user_name = talloc_strdup(result, username);
2393 result->domain = talloc_strdup(result, domain);
2394 if ((result->user_name == NULL) || (result->domain == NULL)) {
2395 status = NT_STATUS_NO_MEMORY;
2396 goto fail;
2399 status = auth_generic_client_prepare(result,
2400 &auth_generic_ctx);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 goto fail;
2405 status = auth_generic_set_username(auth_generic_ctx, username);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 goto fail;
2410 status = auth_generic_set_domain(auth_generic_ctx, domain);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 goto fail;
2415 status = auth_generic_set_password(auth_generic_ctx, password);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 goto fail;
2420 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 goto fail;
2425 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 goto fail;
2430 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2431 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2433 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2434 if (!NT_STATUS_IS_OK(status)) {
2435 goto fail;
2438 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2439 talloc_free(auth_generic_ctx);
2440 *presult = result;
2441 return NT_STATUS_OK;
2443 fail:
2444 TALLOC_FREE(result);
2445 return status;
2449 * Create an rpc pipe client struct, connecting to a tcp port.
2451 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2452 const struct sockaddr_storage *ss_addr,
2453 uint16_t port,
2454 const struct ndr_interface_table *table,
2455 struct rpc_pipe_client **presult)
2457 struct rpc_pipe_client *result;
2458 struct sockaddr_storage addr;
2459 NTSTATUS status;
2460 int fd;
2462 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2463 if (result == NULL) {
2464 return NT_STATUS_NO_MEMORY;
2467 result->abstract_syntax = table->syntax_id;
2468 result->transfer_syntax = ndr_transfer_syntax_ndr;
2470 result->desthost = talloc_strdup(result, host);
2471 result->srv_name_slash = talloc_asprintf_strupper_m(
2472 result, "\\\\%s", result->desthost);
2473 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2474 status = NT_STATUS_NO_MEMORY;
2475 goto fail;
2478 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2479 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2481 if (ss_addr == NULL) {
2482 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2483 status = NT_STATUS_NOT_FOUND;
2484 goto fail;
2486 } else {
2487 addr = *ss_addr;
2490 status = open_socket_out(&addr, port, 60*1000, &fd);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 goto fail;
2494 set_socket_options(fd, lp_socket_options());
2496 status = rpc_transport_sock_init(result, fd, &result->transport);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 close(fd);
2499 goto fail;
2502 result->transport->transport = NCACN_IP_TCP;
2504 result->binding_handle = rpccli_bh_create(result, NULL, table);
2505 if (result->binding_handle == NULL) {
2506 TALLOC_FREE(result);
2507 return NT_STATUS_NO_MEMORY;
2510 *presult = result;
2511 return NT_STATUS_OK;
2513 fail:
2514 TALLOC_FREE(result);
2515 return status;
2519 * Determine the tcp port on which a dcerpc interface is listening
2520 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2521 * target host.
2523 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2524 const struct sockaddr_storage *addr,
2525 const struct ndr_interface_table *table,
2526 uint16_t *pport)
2528 NTSTATUS status;
2529 struct rpc_pipe_client *epm_pipe = NULL;
2530 struct dcerpc_binding_handle *epm_handle = NULL;
2531 struct pipe_auth_data *auth = NULL;
2532 struct dcerpc_binding *map_binding = NULL;
2533 struct dcerpc_binding *res_binding = NULL;
2534 enum dcerpc_transport_t transport;
2535 const char *endpoint = NULL;
2536 struct epm_twr_t *map_tower = NULL;
2537 struct epm_twr_t *res_towers = NULL;
2538 struct policy_handle *entry_handle = NULL;
2539 uint32_t num_towers = 0;
2540 uint32_t max_towers = 1;
2541 struct epm_twr_p_t towers;
2542 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2543 uint32_t result = 0;
2545 if (pport == NULL) {
2546 status = NT_STATUS_INVALID_PARAMETER;
2547 goto done;
2550 if (ndr_syntax_id_equal(&table->syntax_id,
2551 &ndr_table_epmapper.syntax_id)) {
2552 *pport = 135;
2553 status = NT_STATUS_OK;
2554 goto done;
2557 /* open the connection to the endpoint mapper */
2558 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2559 &ndr_table_epmapper,
2560 &epm_pipe);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 goto done;
2565 epm_handle = epm_pipe->binding_handle;
2567 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 goto done;
2572 status = rpc_pipe_bind(epm_pipe, auth);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 goto done;
2577 /* create tower for asking the epmapper */
2579 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2580 &map_binding);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 goto done;
2585 status = dcerpc_binding_set_abstract_syntax(map_binding,
2586 &table->syntax_id);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 goto done;
2591 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2592 if (map_tower == NULL) {
2593 status = NT_STATUS_NO_MEMORY;
2594 goto done;
2597 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2598 &(map_tower->tower));
2599 if (!NT_STATUS_IS_OK(status)) {
2600 goto done;
2603 /* allocate further parameters for the epm_Map call */
2605 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2606 if (res_towers == NULL) {
2607 status = NT_STATUS_NO_MEMORY;
2608 goto done;
2610 towers.twr = res_towers;
2612 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2613 if (entry_handle == NULL) {
2614 status = NT_STATUS_NO_MEMORY;
2615 goto done;
2618 /* ask the endpoint mapper for the port */
2620 status = dcerpc_epm_Map(epm_handle,
2621 tmp_ctx,
2622 discard_const_p(struct GUID,
2623 &(table->syntax_id.uuid)),
2624 map_tower,
2625 entry_handle,
2626 max_towers,
2627 &num_towers,
2628 &towers,
2629 &result);
2631 if (!NT_STATUS_IS_OK(status)) {
2632 goto done;
2635 if (result != EPMAPPER_STATUS_OK) {
2636 status = NT_STATUS_UNSUCCESSFUL;
2637 goto done;
2640 if (num_towers != 1) {
2641 status = NT_STATUS_UNSUCCESSFUL;
2642 goto done;
2645 /* extract the port from the answer */
2647 status = dcerpc_binding_from_tower(tmp_ctx,
2648 &(towers.twr->tower),
2649 &res_binding);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 goto done;
2654 transport = dcerpc_binding_get_transport(res_binding);
2655 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2657 /* are further checks here necessary? */
2658 if (transport != NCACN_IP_TCP) {
2659 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2660 goto done;
2663 if (endpoint == NULL) {
2664 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2665 goto done;
2668 *pport = (uint16_t)atoi(endpoint);
2670 done:
2671 TALLOC_FREE(tmp_ctx);
2672 return status;
2676 * Create a rpc pipe client struct, connecting to a host via tcp.
2677 * The port is determined by asking the endpoint mapper on the given
2678 * host.
2680 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2681 const struct sockaddr_storage *addr,
2682 const struct ndr_interface_table *table,
2683 struct rpc_pipe_client **presult)
2685 NTSTATUS status;
2686 uint16_t port = 0;
2688 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 return status;
2693 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2694 table, presult);
2697 /********************************************************************
2698 Create a rpc pipe client struct, connecting to a unix domain socket
2699 ********************************************************************/
2700 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2701 const struct ndr_interface_table *table,
2702 struct rpc_pipe_client **presult)
2704 struct rpc_pipe_client *result;
2705 struct sockaddr_un addr;
2706 NTSTATUS status;
2707 int fd;
2708 socklen_t salen;
2710 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2711 if (result == NULL) {
2712 return NT_STATUS_NO_MEMORY;
2715 result->abstract_syntax = table->syntax_id;
2716 result->transfer_syntax = ndr_transfer_syntax_ndr;
2718 result->desthost = get_myname(result);
2719 result->srv_name_slash = talloc_asprintf_strupper_m(
2720 result, "\\\\%s", result->desthost);
2721 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2722 status = NT_STATUS_NO_MEMORY;
2723 goto fail;
2726 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2727 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2729 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2730 if (fd == -1) {
2731 status = map_nt_error_from_unix(errno);
2732 goto fail;
2735 ZERO_STRUCT(addr);
2736 addr.sun_family = AF_UNIX;
2737 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2738 salen = sizeof(struct sockaddr_un);
2740 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2741 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2742 strerror(errno)));
2743 close(fd);
2744 return map_nt_error_from_unix(errno);
2747 status = rpc_transport_sock_init(result, fd, &result->transport);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 close(fd);
2750 goto fail;
2753 result->transport->transport = NCALRPC;
2755 result->binding_handle = rpccli_bh_create(result, NULL, table);
2756 if (result->binding_handle == NULL) {
2757 TALLOC_FREE(result);
2758 return NT_STATUS_NO_MEMORY;
2761 *presult = result;
2762 return NT_STATUS_OK;
2764 fail:
2765 TALLOC_FREE(result);
2766 return status;
2769 struct rpc_pipe_client_np_ref {
2770 struct cli_state *cli;
2771 struct rpc_pipe_client *pipe;
2774 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2776 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2777 return 0;
2780 /****************************************************************************
2781 Open a named pipe over SMB to a remote server.
2783 * CAVEAT CALLER OF THIS FUNCTION:
2784 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2785 * so be sure that this function is called AFTER any structure (vs pointer)
2786 * assignment of the cli. In particular, libsmbclient does structure
2787 * assignments of cli, which invalidates the data in the returned
2788 * rpc_pipe_client if this function is called before the structure assignment
2789 * of cli.
2791 ****************************************************************************/
2793 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2794 const struct ndr_interface_table *table,
2795 struct rpc_pipe_client **presult)
2797 struct rpc_pipe_client *result;
2798 NTSTATUS status;
2799 struct rpc_pipe_client_np_ref *np_ref;
2801 /* sanity check to protect against crashes */
2803 if ( !cli ) {
2804 return NT_STATUS_INVALID_HANDLE;
2807 result = talloc_zero(NULL, struct rpc_pipe_client);
2808 if (result == NULL) {
2809 return NT_STATUS_NO_MEMORY;
2812 result->abstract_syntax = table->syntax_id;
2813 result->transfer_syntax = ndr_transfer_syntax_ndr;
2814 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2815 result->srv_name_slash = talloc_asprintf_strupper_m(
2816 result, "\\\\%s", result->desthost);
2818 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2819 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2821 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2822 TALLOC_FREE(result);
2823 return NT_STATUS_NO_MEMORY;
2826 status = rpc_transport_np_init(result, cli, table,
2827 &result->transport);
2828 if (!NT_STATUS_IS_OK(status)) {
2829 TALLOC_FREE(result);
2830 return status;
2833 result->transport->transport = NCACN_NP;
2835 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2836 if (np_ref == NULL) {
2837 TALLOC_FREE(result);
2838 return NT_STATUS_NO_MEMORY;
2840 np_ref->cli = cli;
2841 np_ref->pipe = result;
2843 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2844 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2846 result->binding_handle = rpccli_bh_create(result, NULL, table);
2847 if (result->binding_handle == NULL) {
2848 TALLOC_FREE(result);
2849 return NT_STATUS_NO_MEMORY;
2852 *presult = result;
2853 return NT_STATUS_OK;
2856 /****************************************************************************
2857 Open a pipe to a remote server.
2858 ****************************************************************************/
2860 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2861 enum dcerpc_transport_t transport,
2862 const struct ndr_interface_table *table,
2863 struct rpc_pipe_client **presult)
2865 switch (transport) {
2866 case NCACN_IP_TCP:
2867 return rpc_pipe_open_tcp(NULL,
2868 smbXcli_conn_remote_name(cli->conn),
2869 smbXcli_conn_remote_sockaddr(cli->conn),
2870 table, presult);
2871 case NCACN_NP:
2872 return rpc_pipe_open_np(cli, table, presult);
2873 default:
2874 return NT_STATUS_NOT_IMPLEMENTED;
2878 /****************************************************************************
2879 Open a named pipe to an SMB server and bind anonymously.
2880 ****************************************************************************/
2882 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2883 enum dcerpc_transport_t transport,
2884 const struct ndr_interface_table *table,
2885 struct rpc_pipe_client **presult)
2887 struct rpc_pipe_client *result;
2888 struct pipe_auth_data *auth;
2889 NTSTATUS status;
2891 status = cli_rpc_pipe_open(cli, transport, table, &result);
2892 if (!NT_STATUS_IS_OK(status)) {
2893 return status;
2896 status = rpccli_anon_bind_data(result, &auth);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2899 nt_errstr(status)));
2900 TALLOC_FREE(result);
2901 return status;
2905 * This is a bit of an abstraction violation due to the fact that an
2906 * anonymous bind on an authenticated SMB inherits the user/domain
2907 * from the enclosing SMB creds
2910 TALLOC_FREE(auth->user_name);
2911 TALLOC_FREE(auth->domain);
2913 auth->user_name = talloc_strdup(auth, cli->user_name);
2914 auth->domain = talloc_strdup(auth, cli->domain);
2916 if (transport == NCACN_NP) {
2917 struct smbXcli_session *session;
2919 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2920 session = cli->smb2.session;
2921 } else {
2922 session = cli->smb1.session;
2925 status = smbXcli_session_application_key(session, auth,
2926 &auth->transport_session_key);
2927 if (!NT_STATUS_IS_OK(status)) {
2928 auth->transport_session_key = data_blob_null;
2932 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2933 TALLOC_FREE(result);
2934 return NT_STATUS_NO_MEMORY;
2937 status = rpc_pipe_bind(result, auth);
2938 if (!NT_STATUS_IS_OK(status)) {
2939 int lvl = 0;
2940 if (ndr_syntax_id_equal(&table->syntax_id,
2941 &ndr_table_dssetup.syntax_id)) {
2942 /* non AD domains just don't have this pipe, avoid
2943 * level 0 statement in that case - gd */
2944 lvl = 3;
2946 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2947 "%s failed with error %s\n",
2948 table->name,
2949 nt_errstr(status) ));
2950 TALLOC_FREE(result);
2951 return status;
2954 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2955 "%s and bound anonymously.\n",
2956 table->name,
2957 result->desthost));
2959 *presult = result;
2960 return NT_STATUS_OK;
2963 /****************************************************************************
2964 ****************************************************************************/
2966 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2967 const struct ndr_interface_table *table,
2968 struct rpc_pipe_client **presult)
2970 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2971 table, presult);
2974 /****************************************************************************
2975 Open a named pipe to an SMB server and bind using the mech specified
2976 ****************************************************************************/
2978 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2979 const struct ndr_interface_table *table,
2980 enum dcerpc_transport_t transport,
2981 enum dcerpc_AuthType auth_type,
2982 enum dcerpc_AuthLevel auth_level,
2983 const char *server,
2984 const char *domain,
2985 const char *username,
2986 const char *password,
2987 struct rpc_pipe_client **presult)
2989 struct rpc_pipe_client *result;
2990 struct pipe_auth_data *auth = NULL;
2991 const char *target_service = table->authservices->names[0];
2993 NTSTATUS status;
2995 status = cli_rpc_pipe_open(cli, transport, table, &result);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 return status;
3000 status = rpccli_generic_bind_data(result,
3001 auth_type, auth_level,
3002 server, target_service,
3003 domain, username, password,
3004 CRED_AUTO_USE_KERBEROS,
3005 NULL,
3006 &auth);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3009 nt_errstr(status)));
3010 goto err;
3013 status = rpc_pipe_bind(result, auth);
3014 if (!NT_STATUS_IS_OK(status)) {
3015 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3016 nt_errstr(status) ));
3017 goto err;
3020 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3021 "machine %s and bound as user %s\\%s.\n", table->name,
3022 result->desthost, domain, username));
3024 *presult = result;
3025 return NT_STATUS_OK;
3027 err:
3029 TALLOC_FREE(result);
3030 return status;
3033 /****************************************************************************
3034 External interface.
3035 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3036 using session_key. sign and seal.
3038 The *pdc will be stolen onto this new pipe
3039 ****************************************************************************/
3041 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3042 const struct ndr_interface_table *table,
3043 enum dcerpc_transport_t transport,
3044 const char *domain,
3045 struct netlogon_creds_cli_context *netlogon_creds,
3046 struct rpc_pipe_client **_rpccli)
3048 struct rpc_pipe_client *rpccli;
3049 struct pipe_auth_data *rpcauth;
3050 struct netlogon_creds_CredentialState *creds = NULL;
3051 enum dcerpc_AuthLevel auth_level;
3052 NTSTATUS status;
3053 const char *target_service = table->authservices->names[0];
3054 int rpc_pipe_bind_dbglvl = 0;
3056 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3057 if (!NT_STATUS_IS_OK(status)) {
3058 return status;
3061 status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds);
3062 if (!NT_STATUS_IS_OK(status)) {
3063 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3064 nt_errstr(status)));
3065 TALLOC_FREE(rpccli);
3066 return status;
3069 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3071 status = rpccli_generic_bind_data(rpccli,
3072 DCERPC_AUTH_TYPE_SCHANNEL,
3073 auth_level,
3074 NULL,
3075 target_service,
3076 domain,
3077 creds->computer_name,
3078 NULL,
3079 CRED_AUTO_USE_KERBEROS,
3080 creds,
3081 &rpcauth);
3082 if (!NT_STATUS_IS_OK(status)) {
3083 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3084 nt_errstr(status)));
3085 TALLOC_FREE(rpccli);
3086 return status;
3089 status = rpc_pipe_bind(rpccli, rpcauth);
3090 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3091 rpc_pipe_bind_dbglvl = 1;
3092 netlogon_creds_cli_delete(netlogon_creds, &creds);
3094 if (!NT_STATUS_IS_OK(status)) {
3095 DEBUG(rpc_pipe_bind_dbglvl,
3096 ("cli_rpc_pipe_open_schannel_with_key: "
3097 "rpc_pipe_bind failed with error %s\n",
3098 nt_errstr(status)));
3099 TALLOC_FREE(rpccli);
3100 return status;
3103 TALLOC_FREE(creds);
3105 if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3106 goto done;
3109 status = netlogon_creds_cli_check(netlogon_creds,
3110 rpccli->binding_handle);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3113 nt_errstr(status)));
3114 TALLOC_FREE(rpccli);
3115 return status;
3119 done:
3120 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3121 "for domain %s and bound using schannel.\n",
3122 table->name,
3123 rpccli->desthost, domain));
3125 *_rpccli = rpccli;
3126 return NT_STATUS_OK;
3129 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
3130 const struct ndr_interface_table *table,
3131 enum dcerpc_transport_t transport,
3132 const char *oid,
3133 enum dcerpc_AuthLevel auth_level,
3134 const char *server,
3135 const char *domain,
3136 const char *username,
3137 const char *password,
3138 struct rpc_pipe_client **presult)
3140 struct rpc_pipe_client *result;
3141 struct pipe_auth_data *auth = NULL;
3142 const char *target_service = table->authservices->names[0];
3144 NTSTATUS status;
3145 enum credentials_use_kerberos use_kerberos;
3147 if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
3148 use_kerberos = CRED_MUST_USE_KERBEROS;
3149 } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
3150 use_kerberos = CRED_DONT_USE_KERBEROS;
3151 } else {
3152 return NT_STATUS_INVALID_PARAMETER;
3155 status = cli_rpc_pipe_open(cli, transport, table, &result);
3156 if (!NT_STATUS_IS_OK(status)) {
3157 return status;
3160 status = rpccli_generic_bind_data(result,
3161 DCERPC_AUTH_TYPE_SPNEGO, auth_level,
3162 server, target_service,
3163 domain, username, password,
3164 use_kerberos, NULL,
3165 &auth);
3166 if (!NT_STATUS_IS_OK(status)) {
3167 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3168 nt_errstr(status)));
3169 goto err;
3172 status = rpc_pipe_bind(result, auth);
3173 if (!NT_STATUS_IS_OK(status)) {
3174 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
3175 nt_errstr(status) ));
3176 goto err;
3179 DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
3180 "machine %s.\n", table->name,
3181 result->desthost));
3183 *presult = result;
3184 return NT_STATUS_OK;
3186 err:
3188 TALLOC_FREE(result);
3189 return status;
3192 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3193 struct rpc_pipe_client *cli,
3194 DATA_BLOB *session_key)
3196 NTSTATUS status;
3197 struct pipe_auth_data *a;
3198 struct gensec_security *gensec_security;
3199 DATA_BLOB sk = data_blob_null;
3200 bool make_dup = false;
3202 if (!session_key || !cli) {
3203 return NT_STATUS_INVALID_PARAMETER;
3206 a = cli->auth;
3208 if (a == NULL) {
3209 return NT_STATUS_INVALID_PARAMETER;
3212 switch (cli->auth->auth_type) {
3213 case DCERPC_AUTH_TYPE_SPNEGO:
3214 case DCERPC_AUTH_TYPE_NTLMSSP:
3215 case DCERPC_AUTH_TYPE_KRB5:
3216 gensec_security = talloc_get_type_abort(a->auth_ctx,
3217 struct gensec_security);
3218 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3219 if (!NT_STATUS_IS_OK(status)) {
3220 return status;
3222 make_dup = false;
3223 break;
3224 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3225 case DCERPC_AUTH_TYPE_NONE:
3226 sk = data_blob_const(a->transport_session_key.data,
3227 a->transport_session_key.length);
3228 make_dup = true;
3229 break;
3230 default:
3231 break;
3234 if (!sk.data) {
3235 return NT_STATUS_NO_USER_SESSION_KEY;
3238 if (make_dup) {
3239 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3240 } else {
3241 *session_key = sk;
3244 return NT_STATUS_OK;