sharesec: Check if share exists in configuration
[samba.git] / source3 / rpc_client / cli_pipe.c
blob4c70c406dbdeb70901ee22a38b030f269c1501e2
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 #define SOURCE3_LIBRPC_INTERNALS 1
24 #include "includes.h"
25 #include "libsmb/namequery.h"
26 #include "../lib/util/tevent_ntstatus.h"
27 #include "librpc/gen_ndr/ndr_epmapper_c.h"
28 #include "../librpc/gen_ndr/ndr_dssetup.h"
29 #include "../libcli/auth/schannel.h"
30 #include "../libcli/auth/netlogon_creds_cli.h"
31 #include "auth_generic.h"
32 #include "librpc/gen_ndr/ndr_dcerpc.h"
33 #include "librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "librpc/gen_ndr/auth.h"
35 #include "librpc/rpc/dcerpc.h"
36 #include "librpc/rpc/dcerpc_internal.h"
37 #include "librpc/rpc/dcerpc_util.h"
38 #include "rpc_dce.h"
39 #include "cli_pipe.h"
40 #include "libsmb/libsmb.h"
41 #include "auth/gensec/gensec.h"
42 #include "auth/credentials/credentials.h"
43 #include "auth/auth_util.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/tsocket/tsocket.h"
46 #include "libcli/named_pipe_auth/npa_tstream.h"
47 #include "librpc/gen_ndr/ndr_winreg.h"
48 #include "local_np.h"
49 #include "libcli/smb/tstream_smbXcli_np.h"
51 #undef DBGC_CLASS
52 #define DBGC_CLASS DBGC_RPC_CLI
54 static const uint16_t default_bt_features =
55 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN |
56 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
58 struct rpc_client_association {
59 struct dcerpc_binding *binding;
61 struct {
62 uint16_t client;
63 uint16_t negotiated;
64 bool negotiation_done;
65 } features;
67 struct samba_sockaddr addr;
69 uint32_t next_call_id;
72 static NTSTATUS rpc_client_association_create(TALLOC_CTX *mem_ctx,
73 uint16_t client_features,
74 uint32_t flags,
75 const char *target_hostname,
76 enum dcerpc_transport_t transport,
77 const struct samba_sockaddr *addr,
78 const char *endpoint,
79 struct rpc_client_association **passoc)
81 struct rpc_client_association *assoc = NULL;
82 struct dcerpc_binding *bd = NULL;
83 char addrstr[INET6_ADDRSTRLEN] = { 0, };
84 NTSTATUS status;
86 assoc = talloc_zero(mem_ctx, struct rpc_client_association);
87 if (assoc == NULL) {
88 return NT_STATUS_NO_MEMORY;
90 assoc->features.client = client_features;
91 if (client_features == 0) {
93 * Without requested features there
94 * is no point in trying to negotiate
95 * something, so we are done...
97 assoc->features.negotiation_done = true;
100 status = dcerpc_parse_binding(assoc, "", &bd);
101 if (!NT_STATUS_IS_OK(status)) {
102 TALLOC_FREE(assoc);
103 return status;
105 status = dcerpc_binding_set_transport(bd, transport);
106 if (!NT_STATUS_IS_OK(status)) {
107 TALLOC_FREE(assoc);
108 return status;
110 switch (addr->u.sa.sa_family) {
111 case AF_INET:
112 case AF_INET6:
113 print_sockaddr(addrstr,
114 sizeof(addrstr),
115 &addr->u.ss);
116 status = dcerpc_binding_set_string_option(bd,
117 "host",
118 addrstr);
119 if (!NT_STATUS_IS_OK(status)) {
120 TALLOC_FREE(assoc);
121 return status;
123 break;
124 default:
125 status = dcerpc_binding_set_string_option(bd,
126 "host",
127 target_hostname);
128 if (!NT_STATUS_IS_OK(status)) {
129 TALLOC_FREE(assoc);
130 return status;
132 break;
134 status = dcerpc_binding_set_string_option(bd,
135 "target_hostname",
136 target_hostname);
137 if (!NT_STATUS_IS_OK(status)) {
138 TALLOC_FREE(assoc);
139 return status;
141 status = dcerpc_binding_set_string_option(bd,
142 "endpoint",
143 endpoint);
144 if (!NT_STATUS_IS_OK(status)) {
145 TALLOC_FREE(assoc);
146 return status;
148 status = dcerpc_binding_set_flags(bd, flags, 0);
149 if (!NT_STATUS_IS_OK(status)) {
150 TALLOC_FREE(assoc);
151 return status;
154 assoc->binding = bd;
155 assoc->addr = *addr;
157 *passoc = assoc;
158 return NT_STATUS_OK;
161 struct rpc_client_connection {
162 DATA_BLOB transport_session_key;
163 struct rpc_cli_transport *transport;
164 struct samba_sockaddr localaddr;
166 struct {
167 uint16_t max_xmit_frag;
168 uint16_t max_recv_frag;
169 bool client_hdr_signing;
170 bool hdr_signing;
171 bool bind_done;
172 } features;
174 uint32_t next_auth_context_id;
175 uint16_t next_pres_context_id;
178 static NTSTATUS rpc_client_connection_create(TALLOC_CTX *mem_ctx,
179 const struct rpc_client_association *assoc,
180 uint16_t max_frag,
181 struct rpc_client_connection **pconn)
183 struct rpc_client_connection *conn = NULL;
184 uint32_t flags = dcerpc_binding_get_flags(assoc->binding);
185 bool client_hdr_signing = (flags & DCERPC_PROPOSE_HEADER_SIGNING);
187 conn = talloc_zero(mem_ctx, struct rpc_client_connection);
188 if (conn == NULL) {
189 return NT_STATUS_NO_MEMORY;
191 conn->features.max_xmit_frag = max_frag;
192 conn->features.max_recv_frag = max_frag;
193 conn->features.client_hdr_signing = client_hdr_signing;
195 *pconn = conn;
196 return NT_STATUS_OK;
199 static int rpc_pipe_client_wrap_destructor(struct rpc_pipe_client *p)
201 if (p->np_cli != NULL) {
202 DLIST_REMOVE(p->np_cli->pipe_list, p);
203 p->np_cli = NULL;
206 return 0;
209 static NTSTATUS rpc_pipe_wrap_create(
210 const struct ndr_interface_table *table,
211 struct cli_state *np_cli,
212 struct rpc_client_association **passoc,
213 struct rpc_client_connection **pconn,
214 TALLOC_CTX *mem_ctx,
215 struct rpc_pipe_client **presult)
217 struct rpc_pipe_client *result = NULL;
218 const char *hostname = NULL;
220 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
221 if (result == NULL) {
222 return NT_STATUS_NO_MEMORY;
224 talloc_set_destructor(result, rpc_pipe_client_wrap_destructor);
226 result->assoc = talloc_move(result, passoc);
227 result->conn = talloc_move(result, pconn);
229 /* rpc_pipe_bind_send should allocate an id... */
230 result->pres_context_id = UINT16_MAX;
231 result->table = table;
232 result->transfer_syntax = ndr_transfer_syntax_ndr;
234 hostname = dcerpc_binding_get_string_option(result->assoc->binding,
235 "target_hostname");
236 result->desthost = talloc_strdup(result, hostname);
237 if (result->desthost == NULL) {
238 TALLOC_FREE(result);
239 return NT_STATUS_NO_MEMORY;
242 result->srv_name_slash = talloc_asprintf_strupper_m(
243 result, "\\\\%s", result->desthost);
244 if (result->srv_name_slash == NULL) {
245 TALLOC_FREE(result);
246 return NT_STATUS_NO_MEMORY;
249 if (np_cli != NULL) {
250 result->np_cli = np_cli;
251 DLIST_ADD_END(np_cli->pipe_list, result);
254 *presult = result;
255 return NT_STATUS_OK;
258 /********************************************************************
259 Pipe description for a DEBUG
260 ********************************************************************/
261 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
262 struct rpc_pipe_client *cli)
264 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
265 if (result == NULL) {
266 return "pipe";
268 return result;
271 /*******************************************************************
272 Use SMBreadX to get rest of one fragment's worth of rpc data.
273 Reads the whole size or give an error message
274 ********************************************************************/
276 struct rpc_read_state {
277 struct tevent_context *ev;
278 struct rpc_cli_transport *transport;
279 uint8_t *data;
280 size_t size;
281 size_t num_read;
284 static void rpc_read_done(struct tevent_req *subreq);
286 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
287 struct tevent_context *ev,
288 struct rpc_cli_transport *transport,
289 uint8_t *data, size_t size)
291 struct tevent_req *req, *subreq;
292 struct rpc_read_state *state;
294 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
295 if (req == NULL) {
296 return NULL;
298 state->ev = ev;
299 state->transport = transport;
300 state->data = data;
301 state->size = size;
302 state->num_read = 0;
304 DBG_INFO("data_to_read: %zu\n", size);
306 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
307 transport->priv);
308 if (subreq == NULL) {
309 goto fail;
311 tevent_req_set_callback(subreq, rpc_read_done, req);
312 return req;
314 fail:
315 TALLOC_FREE(req);
316 return NULL;
319 static void rpc_read_done(struct tevent_req *subreq)
321 struct tevent_req *req = tevent_req_callback_data(
322 subreq, struct tevent_req);
323 struct rpc_read_state *state = tevent_req_data(
324 req, struct rpc_read_state);
325 NTSTATUS status;
326 ssize_t received;
328 status = state->transport->read_recv(subreq, &received);
329 TALLOC_FREE(subreq);
330 if (tevent_req_nterror(req, status)) {
331 return;
334 state->num_read += received;
335 if (state->num_read == state->size) {
336 tevent_req_done(req);
337 return;
340 subreq = state->transport->read_send(state, state->ev,
341 state->data + state->num_read,
342 state->size - state->num_read,
343 state->transport->priv);
344 if (tevent_req_nomem(subreq, req)) {
345 return;
347 tevent_req_set_callback(subreq, rpc_read_done, req);
350 static NTSTATUS rpc_read_recv(struct tevent_req *req)
352 return tevent_req_simple_recv_ntstatus(req);
355 struct rpc_write_state {
356 struct tevent_context *ev;
357 struct rpc_cli_transport *transport;
358 const uint8_t *data;
359 size_t size;
360 size_t num_written;
363 static void rpc_write_done(struct tevent_req *subreq);
365 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
366 struct tevent_context *ev,
367 struct rpc_cli_transport *transport,
368 const uint8_t *data, size_t size)
370 struct tevent_req *req, *subreq;
371 struct rpc_write_state *state;
373 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
374 if (req == NULL) {
375 return NULL;
377 state->ev = ev;
378 state->transport = transport;
379 state->data = data;
380 state->size = size;
381 state->num_written = 0;
383 DBG_INFO("data_to_write: %zu\n", size);
385 subreq = transport->write_send(state, ev, data, size, transport->priv);
386 if (tevent_req_nomem(subreq, req)) {
387 return tevent_req_post(req, ev);
389 tevent_req_set_callback(subreq, rpc_write_done, req);
390 return req;
393 static void rpc_write_done(struct tevent_req *subreq)
395 struct tevent_req *req = tevent_req_callback_data(
396 subreq, struct tevent_req);
397 struct rpc_write_state *state = tevent_req_data(
398 req, struct rpc_write_state);
399 NTSTATUS status;
400 ssize_t written;
402 status = state->transport->write_recv(subreq, &written);
403 TALLOC_FREE(subreq);
404 if (tevent_req_nterror(req, status)) {
405 return;
408 state->num_written += written;
410 if (state->num_written == state->size) {
411 tevent_req_done(req);
412 return;
415 subreq = state->transport->write_send(state, state->ev,
416 state->data + state->num_written,
417 state->size - state->num_written,
418 state->transport->priv);
419 if (tevent_req_nomem(subreq, req)) {
420 return;
422 tevent_req_set_callback(subreq, rpc_write_done, req);
425 static NTSTATUS rpc_write_recv(struct tevent_req *req)
427 return tevent_req_simple_recv_ntstatus(req);
431 /****************************************************************************
432 Try and get a PDU's worth of data from current_pdu. If not, then read more
433 from the wire.
434 ****************************************************************************/
436 struct get_complete_frag_state {
437 struct tevent_context *ev;
438 struct rpc_pipe_client *cli;
439 uint16_t frag_len;
440 DATA_BLOB *pdu;
443 static void get_complete_frag_got_header(struct tevent_req *subreq);
444 static void get_complete_frag_got_rest(struct tevent_req *subreq);
446 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
447 struct tevent_context *ev,
448 struct rpc_pipe_client *cli,
449 DATA_BLOB *pdu)
451 struct tevent_req *req, *subreq;
452 struct get_complete_frag_state *state;
453 size_t received;
455 req = tevent_req_create(mem_ctx, &state,
456 struct get_complete_frag_state);
457 if (req == NULL) {
458 return NULL;
460 state->ev = ev;
461 state->cli = cli;
462 state->frag_len = RPC_HEADER_LEN;
463 state->pdu = pdu;
465 received = pdu->length;
466 if (received < RPC_HEADER_LEN) {
467 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
468 tevent_req_oom(req);
469 return tevent_req_post(req, ev);
471 subreq = rpc_read_send(state, state->ev,
472 state->cli->conn->transport,
473 pdu->data + received,
474 RPC_HEADER_LEN - received);
475 if (tevent_req_nomem(subreq, req)) {
476 return tevent_req_post(req, ev);
478 tevent_req_set_callback(subreq, get_complete_frag_got_header,
479 req);
480 return req;
483 state->frag_len = dcerpc_get_frag_length(pdu);
484 if (state->frag_len < RPC_HEADER_LEN) {
485 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
486 return tevent_req_post(req, ev);
489 if (received >= state->frag_len) {
491 * Got the whole fragment
493 tevent_req_done(req);
494 return tevent_req_post(req, ev);
497 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
498 tevent_req_oom(req);
499 return tevent_req_post(req, ev);
502 subreq = rpc_read_send(
503 state,
504 state->ev,
505 state->cli->conn->transport,
506 pdu->data + received,
507 state->frag_len - received);
508 if (tevent_req_nomem(subreq, req)) {
509 return tevent_req_post(req, ev);
511 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
512 return req;
515 static void get_complete_frag_got_header(struct tevent_req *subreq)
517 struct tevent_req *req = tevent_req_callback_data(
518 subreq, struct tevent_req);
519 struct get_complete_frag_state *state = tevent_req_data(
520 req, struct get_complete_frag_state);
521 NTSTATUS status;
523 status = rpc_read_recv(subreq);
524 TALLOC_FREE(subreq);
525 if (tevent_req_nterror(req, status)) {
526 return;
529 state->frag_len = dcerpc_get_frag_length(state->pdu);
530 if (state->frag_len < RPC_HEADER_LEN) {
531 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
532 return;
535 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
536 tevent_req_oom(req);
537 return;
541 * We're here in this piece of code because we've read exactly
542 * RPC_HEADER_LEN bytes into state->pdu.
545 subreq = rpc_read_send(state, state->ev,
546 state->cli->conn->transport,
547 state->pdu->data + RPC_HEADER_LEN,
548 state->frag_len - RPC_HEADER_LEN);
549 if (tevent_req_nomem(subreq, req)) {
550 return;
552 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
555 static void get_complete_frag_got_rest(struct tevent_req *subreq)
557 NTSTATUS status = rpc_read_recv(subreq);
558 return tevent_req_simple_finish_ntstatus(subreq, status);
561 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
563 return tevent_req_simple_recv_ntstatus(req);
566 /****************************************************************************
567 Do basic authentication checks on an incoming pdu.
568 ****************************************************************************/
570 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
571 struct rpc_pipe_client *cli,
572 struct ncacn_packet *pkt,
573 DATA_BLOB *pdu,
574 uint8_t expected_pkt_type,
575 uint32_t call_id,
576 DATA_BLOB *rdata,
577 DATA_BLOB *reply_pdu)
579 const struct dcerpc_response *r = NULL;
580 DATA_BLOB tmp_stub = { .data = NULL };
581 NTSTATUS ret;
584 * Point the return values at the real data including the RPC
585 * header. Just in case the caller wants it.
587 *rdata = *pdu;
589 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
590 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
592 * TODO: do we still need this hack which was introduced
593 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
595 * I don't even know what AS/U might be...
597 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
598 "fragment first/last ON.\n"));
599 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
602 /* Ensure we have the correct type. */
603 switch (pkt->ptype) {
604 case DCERPC_PKT_BIND_NAK:
605 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
606 rpccli_pipe_txt(talloc_tos(), cli)));
608 ret = dcerpc_verify_ncacn_packet_header(pkt,
609 DCERPC_PKT_BIND_NAK,
610 0, /* max_auth_info */
611 DCERPC_PFC_FLAG_FIRST |
612 DCERPC_PFC_FLAG_LAST,
613 0); /* optional flags */
614 if (!NT_STATUS_IS_OK(ret)) {
615 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
616 "RPC packet type - %u, expected %u: %s\n",
617 rpccli_pipe_txt(talloc_tos(), cli),
618 pkt->ptype, expected_pkt_type,
619 nt_errstr(ret)));
620 NDR_PRINT_DEBUG(ncacn_packet, pkt);
621 return ret;
624 /* Use this for now... */
625 return NT_STATUS_NETWORK_ACCESS_DENIED;
627 case DCERPC_PKT_BIND_ACK:
628 ret = dcerpc_verify_ncacn_packet_header(pkt,
629 expected_pkt_type,
630 pkt->u.bind_ack.auth_info.length,
631 DCERPC_PFC_FLAG_FIRST |
632 DCERPC_PFC_FLAG_LAST,
633 DCERPC_PFC_FLAG_CONC_MPX |
634 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
635 if (!NT_STATUS_IS_OK(ret)) {
636 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
637 "RPC packet type - %u, expected %u: %s\n",
638 rpccli_pipe_txt(talloc_tos(), cli),
639 pkt->ptype, expected_pkt_type,
640 nt_errstr(ret)));
641 NDR_PRINT_DEBUG(ncacn_packet, pkt);
642 return ret;
645 break;
647 case DCERPC_PKT_ALTER_RESP:
648 ret = dcerpc_verify_ncacn_packet_header(pkt,
649 expected_pkt_type,
650 pkt->u.alter_resp.auth_info.length,
651 DCERPC_PFC_FLAG_FIRST |
652 DCERPC_PFC_FLAG_LAST,
653 DCERPC_PFC_FLAG_CONC_MPX |
654 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
655 if (!NT_STATUS_IS_OK(ret)) {
656 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
657 "RPC packet type - %u, expected %u: %s\n",
658 rpccli_pipe_txt(talloc_tos(), cli),
659 pkt->ptype, expected_pkt_type,
660 nt_errstr(ret)));
661 NDR_PRINT_DEBUG(ncacn_packet, pkt);
662 return ret;
665 break;
667 case DCERPC_PKT_RESPONSE:
669 r = &pkt->u.response;
671 ret = dcerpc_verify_ncacn_packet_header(pkt,
672 expected_pkt_type,
673 r->stub_and_verifier.length,
674 0, /* required_flags */
675 DCERPC_PFC_FLAG_FIRST |
676 DCERPC_PFC_FLAG_LAST);
677 if (!NT_STATUS_IS_OK(ret)) {
678 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
679 "RPC packet type - %u, expected %u: %s\n",
680 rpccli_pipe_txt(talloc_tos(), cli),
681 pkt->ptype, expected_pkt_type,
682 nt_errstr(ret)));
683 NDR_PRINT_DEBUG(ncacn_packet, pkt);
684 return ret;
687 tmp_stub.data = r->stub_and_verifier.data;
688 tmp_stub.length = r->stub_and_verifier.length;
690 /* Here's where we deal with incoming sign/seal. */
691 ret = dcerpc_check_auth(cli->auth, pkt,
692 &tmp_stub,
693 DCERPC_RESPONSE_LENGTH,
694 pdu);
695 if (!NT_STATUS_IS_OK(ret)) {
696 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
697 "RPC packet type - %u, expected %u: %s\n",
698 rpccli_pipe_txt(talloc_tos(), cli),
699 pkt->ptype, expected_pkt_type,
700 nt_errstr(ret)));
701 NDR_PRINT_DEBUG(ncacn_packet, pkt);
702 return ret;
705 /* Point the return values at the NDR data. */
706 *rdata = tmp_stub;
708 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
709 (long unsigned int)pdu->length,
710 (long unsigned int)rdata->length));
713 * If this is the first reply, and the allocation hint is
714 * reasonable, try and set up the reply_pdu DATA_BLOB to the
715 * correct size.
718 if ((reply_pdu->length == 0) &&
719 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
720 if (!data_blob_realloc(mem_ctx, reply_pdu,
721 r->alloc_hint)) {
722 DEBUG(0, ("reply alloc hint %d too "
723 "large to allocate\n",
724 (int)r->alloc_hint));
725 return NT_STATUS_NO_MEMORY;
729 break;
731 case DCERPC_PKT_FAULT:
733 ret = dcerpc_verify_ncacn_packet_header(pkt,
734 DCERPC_PKT_FAULT,
735 0, /* max_auth_info */
736 DCERPC_PFC_FLAG_FIRST |
737 DCERPC_PFC_FLAG_LAST,
738 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
739 if (!NT_STATUS_IS_OK(ret)) {
740 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
741 "RPC packet type - %u, expected %u: %s\n",
742 rpccli_pipe_txt(talloc_tos(), cli),
743 pkt->ptype, expected_pkt_type,
744 nt_errstr(ret)));
745 NDR_PRINT_DEBUG(ncacn_packet, pkt);
746 return ret;
749 DEBUG(1, (__location__ ": RPC fault code %s received "
750 "from %s!\n",
751 dcerpc_errstr(talloc_tos(),
752 pkt->u.fault.status),
753 rpccli_pipe_txt(talloc_tos(), cli)));
755 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
757 default:
758 DEBUG(0, (__location__ "Unknown packet type %u received "
759 "from %s!\n",
760 (unsigned int)pkt->ptype,
761 rpccli_pipe_txt(talloc_tos(), cli)));
762 return NT_STATUS_RPC_PROTOCOL_ERROR;
766 if (pkt->call_id != call_id) {
767 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
768 "RPC call_id - %u, not %u\n",
769 rpccli_pipe_txt(talloc_tos(), cli),
770 pkt->call_id, call_id));
771 return NT_STATUS_RPC_PROTOCOL_ERROR;
774 return NT_STATUS_OK;
777 /****************************************************************************
778 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
779 ****************************************************************************/
781 struct cli_api_pipe_state {
782 struct tevent_context *ev;
783 struct rpc_cli_transport *transport;
784 uint8_t *rdata;
785 uint32_t rdata_len;
788 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
789 static void cli_api_pipe_write_done(struct tevent_req *subreq);
790 static void cli_api_pipe_read_done(struct tevent_req *subreq);
792 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
793 struct tevent_context *ev,
794 struct rpc_cli_transport *transport,
795 uint8_t *data, size_t data_len,
796 uint32_t max_rdata_len)
798 struct tevent_req *req, *subreq;
799 struct cli_api_pipe_state *state;
801 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
802 if (req == NULL) {
803 return NULL;
805 state->ev = ev;
806 state->transport = transport;
808 if (max_rdata_len < RPC_HEADER_LEN) {
810 * For a RPC reply we always need at least RPC_HEADER_LEN
811 * bytes. We check this here because we will receive
812 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
814 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
815 return tevent_req_post(req, ev);
818 if (transport->trans_send != NULL) {
819 subreq = transport->trans_send(state, ev, data, data_len,
820 max_rdata_len, transport->priv);
821 if (tevent_req_nomem(subreq, req)) {
822 return tevent_req_post(req, ev);
824 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
825 return req;
829 * If the transport does not provide a "trans" routine, i.e. for
830 * example the ncacn_ip_tcp transport, do the write/read step here.
833 subreq = rpc_write_send(state, ev, transport, data, data_len);
834 if (tevent_req_nomem(subreq, req)) {
835 return tevent_req_post(req, ev);
837 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
838 return req;
841 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
843 struct tevent_req *req = tevent_req_callback_data(
844 subreq, struct tevent_req);
845 struct cli_api_pipe_state *state = tevent_req_data(
846 req, struct cli_api_pipe_state);
847 NTSTATUS status;
849 status = state->transport->trans_recv(subreq, state, &state->rdata,
850 &state->rdata_len);
851 TALLOC_FREE(subreq);
852 if (tevent_req_nterror(req, status)) {
853 return;
855 tevent_req_done(req);
858 static void cli_api_pipe_write_done(struct tevent_req *subreq)
860 struct tevent_req *req = tevent_req_callback_data(
861 subreq, struct tevent_req);
862 struct cli_api_pipe_state *state = tevent_req_data(
863 req, struct cli_api_pipe_state);
864 NTSTATUS status;
866 status = rpc_write_recv(subreq);
867 TALLOC_FREE(subreq);
868 if (tevent_req_nterror(req, status)) {
869 return;
872 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
873 if (tevent_req_nomem(state->rdata, req)) {
874 return;
878 * We don't need to use rpc_read_send here, the upper layer will cope
879 * with a short read, transport->trans_send could also return less
880 * than state->max_rdata_len.
882 subreq = state->transport->read_send(state, state->ev, state->rdata,
883 RPC_HEADER_LEN,
884 state->transport->priv);
885 if (tevent_req_nomem(subreq, req)) {
886 return;
888 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
891 static void cli_api_pipe_read_done(struct tevent_req *subreq)
893 struct tevent_req *req = tevent_req_callback_data(
894 subreq, struct tevent_req);
895 struct cli_api_pipe_state *state = tevent_req_data(
896 req, struct cli_api_pipe_state);
897 NTSTATUS status;
898 ssize_t received;
900 status = state->transport->read_recv(subreq, &received);
901 TALLOC_FREE(subreq);
902 if (tevent_req_nterror(req, status)) {
903 return;
905 state->rdata_len = received;
906 tevent_req_done(req);
909 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
910 uint8_t **prdata, uint32_t *prdata_len)
912 struct cli_api_pipe_state *state = tevent_req_data(
913 req, struct cli_api_pipe_state);
914 NTSTATUS status;
916 if (tevent_req_is_nterror(req, &status)) {
917 return status;
920 *prdata = talloc_move(mem_ctx, &state->rdata);
921 *prdata_len = state->rdata_len;
922 return NT_STATUS_OK;
925 /****************************************************************************
926 Send data on an rpc pipe via trans. The data must be the last
927 pdu fragment of an NDR data stream.
929 Receive response data from an rpc pipe, which may be large...
931 Read the first fragment: unfortunately have to use SMBtrans for the first
932 bit, then SMBreadX for subsequent bits.
934 If first fragment received also wasn't the last fragment, continue
935 getting fragments until we _do_ receive the last fragment.
937 Request/Response PDU's look like the following...
939 |<------------------PDU len----------------------------------------------->|
940 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
942 +------------+-----------------+-------------+---------------+-------------+
943 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
944 +------------+-----------------+-------------+---------------+-------------+
946 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
947 signing & sealing being negotiated.
949 ****************************************************************************/
951 struct rpc_api_pipe_state {
952 struct tevent_context *ev;
953 struct rpc_pipe_client *cli;
954 uint8_t expected_pkt_type;
955 uint32_t call_id;
957 DATA_BLOB incoming_frag;
958 struct ncacn_packet *pkt;
960 /* Incoming reply */
961 DATA_BLOB reply_pdu;
962 size_t reply_pdu_offset;
963 uint8_t endianness;
966 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
967 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
968 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
970 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
971 struct tevent_context *ev,
972 struct rpc_pipe_client *cli,
973 DATA_BLOB *data, /* Outgoing PDU */
974 uint8_t expected_pkt_type,
975 uint32_t call_id)
977 struct tevent_req *req, *subreq;
978 struct rpc_api_pipe_state *state;
979 uint16_t max_recv_frag;
981 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
982 if (req == NULL) {
983 return NULL;
985 state->ev = ev;
986 state->cli = cli;
987 state->expected_pkt_type = expected_pkt_type;
988 state->call_id = call_id;
989 state->endianness = DCERPC_DREP_LE;
992 * Ensure we're not sending too much.
994 if (data->length > cli->conn->features.max_xmit_frag) {
995 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 return tevent_req_post(req, ev);
999 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1001 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
1002 subreq = rpc_write_send(state, ev, cli->conn->transport,
1003 data->data, data->length);
1004 if (tevent_req_nomem(subreq, req)) {
1005 return tevent_req_post(req, ev);
1007 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
1008 return req;
1011 /* get the header first, then fetch the rest once we have
1012 * the frag_length available */
1013 max_recv_frag = RPC_HEADER_LEN;
1015 subreq = cli_api_pipe_send(state, ev, cli->conn->transport,
1016 data->data, data->length, max_recv_frag);
1017 if (tevent_req_nomem(subreq, req)) {
1018 return tevent_req_post(req, ev);
1020 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1021 return req;
1024 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
1026 NTSTATUS status = rpc_write_recv(subreq);
1027 return tevent_req_simple_finish_ntstatus(subreq, status);
1030 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1032 struct tevent_req *req = tevent_req_callback_data(
1033 subreq, struct tevent_req);
1034 struct rpc_api_pipe_state *state = tevent_req_data(
1035 req, struct rpc_api_pipe_state);
1036 NTSTATUS status;
1037 uint8_t *rdata = NULL;
1038 uint32_t rdata_len = 0;
1040 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1041 TALLOC_FREE(subreq);
1042 if (tevent_req_nterror(req, status)) {;
1043 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1044 return;
1047 if (rdata == NULL) {
1048 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1049 rpccli_pipe_txt(talloc_tos(), state->cli)));
1050 tevent_req_done(req);
1051 return;
1055 * Move data on state->incoming_frag.
1057 state->incoming_frag.data = talloc_move(state, &rdata);
1058 state->incoming_frag.length = rdata_len;
1059 if (!state->incoming_frag.data) {
1060 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1061 return;
1064 /* Ensure we have enough data for a pdu. */
1065 subreq = get_complete_frag_send(state, state->ev, state->cli,
1066 &state->incoming_frag);
1067 if (tevent_req_nomem(subreq, req)) {
1068 return;
1070 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1073 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1075 struct tevent_req *req = tevent_req_callback_data(
1076 subreq, struct tevent_req);
1077 struct rpc_api_pipe_state *state = tevent_req_data(
1078 req, struct rpc_api_pipe_state);
1079 NTSTATUS status;
1080 DATA_BLOB rdata = { .data = NULL };
1082 status = get_complete_frag_recv(subreq);
1083 TALLOC_FREE(subreq);
1084 if (tevent_req_nterror(req, status)) {
1085 DEBUG(5, ("get_complete_frag failed: %s\n",
1086 nt_errstr(status)));
1087 return;
1090 state->pkt = talloc(state, struct ncacn_packet);
1091 if (!state->pkt) {
1093 * TODO: do a real async disconnect ...
1095 * For now do it sync...
1097 TALLOC_FREE(state->cli->conn);
1098 tevent_req_oom(req);
1099 return;
1102 status = dcerpc_pull_ncacn_packet(state->pkt,
1103 &state->incoming_frag,
1104 state->pkt);
1105 if (tevent_req_nterror(req, status)) {
1107 * TODO: do a real async disconnect ...
1109 * For now do it sync...
1111 TALLOC_FREE(state->cli->conn);
1112 return;
1115 if (DEBUGLEVEL >= 10) {
1116 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
1119 status = cli_pipe_validate_current_pdu(state,
1120 state->cli, state->pkt,
1121 &state->incoming_frag,
1122 state->expected_pkt_type,
1123 state->call_id,
1124 &rdata,
1125 &state->reply_pdu);
1127 DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
1128 state->incoming_frag.length,
1129 state->reply_pdu_offset,
1130 nt_errstr(status));
1132 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
1134 * TODO: do a real async disconnect ...
1136 * For now do it sync...
1138 TALLOC_FREE(state->cli->conn);
1139 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1141 * TODO: do a real async disconnect ...
1143 * For now do it sync...
1145 TALLOC_FREE(state->cli->conn);
1146 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1148 * TODO: do a real async disconnect ...
1150 * For now do it sync...
1152 TALLOC_FREE(state->cli->conn);
1154 if (tevent_req_nterror(req, status)) {
1155 return;
1158 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1159 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1161 * Set the data type correctly for big-endian data on the
1162 * first packet.
1164 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1165 "big-endian.\n",
1166 rpccli_pipe_txt(talloc_tos(), state->cli)));
1167 state->endianness = 0x00; /* BIG ENDIAN */
1170 * Check endianness on subsequent packets.
1172 if (state->endianness != state->pkt->drep[0]) {
1173 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1174 "%s\n",
1175 state->endianness?"little":"big",
1176 state->pkt->drep[0]?"little":"big"));
1178 * TODO: do a real async disconnect ...
1180 * For now do it sync...
1182 TALLOC_FREE(state->cli->conn);
1183 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1184 return;
1187 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1189 * TODO: do a real async disconnect ...
1191 * For now do it sync...
1193 TALLOC_FREE(state->cli->conn);
1194 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1195 return;
1198 /* Now copy the data portion out of the pdu into rbuf. */
1199 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1200 if (!data_blob_realloc(NULL, &state->reply_pdu,
1201 state->reply_pdu_offset + rdata.length)) {
1203 * TODO: do a real async disconnect ...
1205 * For now do it sync...
1207 TALLOC_FREE(state->cli->conn);
1208 tevent_req_oom(req);
1209 return;
1213 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1214 rdata.data, rdata.length);
1215 state->reply_pdu_offset += rdata.length;
1217 /* reset state->incoming_frag, there is no need to free it,
1218 * it will be reallocated to the right size the next time
1219 * it is used */
1220 state->incoming_frag.length = 0;
1222 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1223 /* make sure the pdu length is right now that we
1224 * have all the data available (alloc hint may
1225 * have allocated more than was actually used) */
1226 state->reply_pdu.length = state->reply_pdu_offset;
1227 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1228 rpccli_pipe_txt(talloc_tos(), state->cli),
1229 (unsigned)state->reply_pdu.length));
1230 tevent_req_done(req);
1231 return;
1234 subreq = get_complete_frag_send(state, state->ev, state->cli,
1235 &state->incoming_frag);
1236 if (subreq == NULL) {
1238 * TODO: do a real async disconnect ...
1240 * For now do it sync...
1242 TALLOC_FREE(state->cli->conn);
1244 if (tevent_req_nomem(subreq, req)) {
1245 return;
1247 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1250 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1251 struct ncacn_packet **pkt,
1252 DATA_BLOB *reply_pdu)
1254 struct rpc_api_pipe_state *state = tevent_req_data(
1255 req, struct rpc_api_pipe_state);
1256 NTSTATUS status;
1258 if (tevent_req_is_nterror(req, &status)) {
1259 return status;
1262 /* return data to caller and assign it ownership of memory */
1263 if (reply_pdu) {
1264 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1265 reply_pdu->length = state->reply_pdu.length;
1266 state->reply_pdu.length = 0;
1267 } else {
1268 data_blob_free(&state->reply_pdu);
1271 if (pkt) {
1272 *pkt = talloc_steal(mem_ctx, state->pkt);
1275 return NT_STATUS_OK;
1278 /*******************************************************************
1279 Creates NTLMSSP auth bind.
1280 ********************************************************************/
1282 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1283 TALLOC_CTX *mem_ctx,
1284 DATA_BLOB *auth_token)
1286 struct gensec_security *gensec_security;
1287 DATA_BLOB null_blob = { .data = NULL };
1288 NTSTATUS status;
1290 gensec_security = cli->auth->auth_ctx;
1292 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1293 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1295 if (!NT_STATUS_IS_OK(status) &&
1296 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1298 return status;
1301 return status;
1304 /*******************************************************************
1305 Creates the internals of a DCE/RPC bind request or alter context PDU.
1306 ********************************************************************/
1308 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1309 enum dcerpc_pkt_type ptype,
1310 uint32_t rpc_call_id,
1311 struct rpc_client_association *assoc,
1312 struct rpc_client_connection *conn,
1313 uint16_t pres_context_id,
1314 const struct ndr_syntax_id *abstract,
1315 const struct ndr_syntax_id *transfer,
1316 const DATA_BLOB *auth_info,
1317 DATA_BLOB *blob)
1319 uint16_t auth_len = auth_info->length;
1320 NTSTATUS status;
1321 struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
1322 assoc->features.client);
1323 struct dcerpc_ctx_list ctx_list[2] = {
1324 [0] = {
1325 .context_id = pres_context_id,
1326 .num_transfer_syntaxes = 1,
1327 .abstract_syntax = *abstract,
1328 .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
1330 [1] = {
1332 * For now we assume pres_context_id is 0
1333 * because bind time feature negotiation
1334 * only happens once per association,
1335 * with the first DCERPC Bind.
1337 * With that we use pres_context_id + 1,
1338 * but only consume it from conn->next_pres_context_id
1339 * in check_bind_response().
1341 .context_id = pres_context_id + 1,
1342 .num_transfer_syntaxes = 1,
1343 .abstract_syntax = *abstract,
1344 .transfer_syntaxes = &bind_time_features,
1347 uint32_t assoc_group_id =
1348 dcerpc_binding_get_assoc_group_id(assoc->binding);
1349 union dcerpc_payload u = {
1350 .bind.max_xmit_frag = conn->features.max_xmit_frag,
1351 .bind.max_recv_frag = conn->features.max_recv_frag,
1352 .bind.assoc_group_id = assoc_group_id,
1353 .bind.num_contexts = assoc->features.negotiation_done ? 1 : 2,
1354 .bind.ctx_list = ctx_list,
1355 .bind.auth_info = *auth_info,
1357 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1359 if (conn->features.client_hdr_signing &&
1360 auth_len != 0 &&
1361 !conn->features.hdr_signing)
1364 * The first authenticated bind or alter_context
1365 * negotiates header signing
1367 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1370 if (auth_len) {
1371 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1374 status = dcerpc_push_ncacn_packet(mem_ctx,
1375 ptype, pfc_flags,
1376 auth_len,
1377 rpc_call_id,
1379 blob);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1382 return status;
1385 return NT_STATUS_OK;
1388 /*******************************************************************
1389 Creates a DCE/RPC bind request.
1390 ********************************************************************/
1392 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1393 struct rpc_pipe_client *cli,
1394 struct pipe_auth_data *auth,
1395 uint32_t rpc_call_id,
1396 const struct ndr_syntax_id *abstract,
1397 const struct ndr_syntax_id *transfer,
1398 DATA_BLOB *rpc_out)
1400 enum dcerpc_pkt_type ptype = DCERPC_PKT_BIND;
1401 DATA_BLOB auth_token = { .data = NULL };
1402 DATA_BLOB auth_info = { .data = NULL };
1403 NTSTATUS ret;
1405 if (cli->conn->features.bind_done) {
1406 ptype = DCERPC_PKT_ALTER;
1409 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
1410 ret = create_generic_auth_rpc_bind_req(
1411 cli, mem_ctx, &auth_token);
1413 if (!NT_STATUS_IS_OK(ret) &&
1414 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1415 return ret;
1419 if (auth_token.length != 0) {
1420 ret = dcerpc_push_dcerpc_auth(cli,
1421 auth->auth_type,
1422 auth->auth_level,
1423 0, /* auth_pad_length */
1424 auth->auth_context_id,
1425 &auth_token,
1426 &auth_info);
1427 if (!NT_STATUS_IS_OK(ret)) {
1428 return ret;
1430 data_blob_free(&auth_token);
1433 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1434 ptype,
1435 rpc_call_id,
1436 cli->assoc,
1437 cli->conn,
1438 cli->pres_context_id,
1439 abstract,
1440 transfer,
1441 &auth_info,
1442 rpc_out);
1443 data_blob_free(&auth_info);
1445 return ret;
1448 /*******************************************************************
1449 External interface.
1450 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1451 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1452 and deals with signing/sealing details.
1453 ********************************************************************/
1455 struct rpc_api_pipe_req_state {
1456 struct tevent_context *ev;
1457 struct rpc_pipe_client *cli;
1458 uint8_t op_num;
1459 uint32_t call_id;
1460 const DATA_BLOB *req_data;
1461 const struct GUID *object_uuid;
1462 uint32_t req_data_sent;
1463 DATA_BLOB req_trailer;
1464 uint32_t req_trailer_sent;
1465 bool verify_bitmask1;
1466 bool verify_pcontext;
1467 DATA_BLOB rpc_out;
1468 DATA_BLOB reply_pdu;
1471 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1472 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1473 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1474 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1475 bool *is_last_frag);
1477 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1478 struct tevent_context *ev,
1479 struct rpc_pipe_client *cli,
1480 uint8_t op_num,
1481 const struct GUID *object_uuid,
1482 const DATA_BLOB *req_data)
1484 struct tevent_req *req, *subreq;
1485 struct rpc_api_pipe_req_state *state;
1486 NTSTATUS status;
1487 bool is_last_frag;
1489 req = tevent_req_create(mem_ctx, &state,
1490 struct rpc_api_pipe_req_state);
1491 if (req == NULL) {
1492 return NULL;
1494 state->ev = ev;
1495 state->cli = cli;
1496 state->op_num = op_num;
1497 state->object_uuid = object_uuid;
1498 state->req_data = req_data;
1499 state->call_id = ++cli->assoc->next_call_id;
1501 if (cli->conn->features.max_xmit_frag < DCERPC_REQUEST_LENGTH
1502 + RPC_MAX_SIGN_SIZE) {
1503 /* Server is screwed up ! */
1504 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1505 return tevent_req_post(req, ev);
1508 status = prepare_verification_trailer(state);
1509 if (tevent_req_nterror(req, status)) {
1510 return tevent_req_post(req, ev);
1513 status = prepare_next_frag(state, &is_last_frag);
1514 if (tevent_req_nterror(req, status)) {
1515 return tevent_req_post(req, ev);
1518 if (is_last_frag) {
1519 subreq = rpc_api_pipe_send(state, ev, state->cli,
1520 &state->rpc_out,
1521 DCERPC_PKT_RESPONSE,
1522 state->call_id);
1523 if (tevent_req_nomem(subreq, req)) {
1524 return tevent_req_post(req, ev);
1526 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1527 } else {
1528 subreq = rpc_write_send(state, ev, cli->conn->transport,
1529 state->rpc_out.data,
1530 state->rpc_out.length);
1531 if (tevent_req_nomem(subreq, req)) {
1532 return tevent_req_post(req, ev);
1534 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1535 req);
1537 return req;
1540 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1542 struct pipe_auth_data *a = state->cli->auth;
1543 struct dcerpc_sec_verification_trailer *t;
1544 struct ndr_push *ndr = NULL;
1545 enum ndr_err_code ndr_err;
1546 size_t align = 0;
1547 size_t pad = 0;
1549 if (a == NULL) {
1550 return NT_STATUS_OK;
1553 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1554 return NT_STATUS_OK;
1557 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1558 if (t == NULL) {
1559 return NT_STATUS_NO_MEMORY;
1562 if (!a->verified_bitmask1) {
1563 t->commands = talloc_realloc(t, t->commands,
1564 struct dcerpc_sec_vt,
1565 t->count.count + 1);
1566 if (t->commands == NULL) {
1567 return NT_STATUS_NO_MEMORY;
1569 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1570 .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
1571 .u.bitmask1 = (state->cli->conn->features.client_hdr_signing) ?
1572 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
1575 state->verify_bitmask1 = true;
1578 if (!state->cli->verified_pcontext) {
1579 t->commands = talloc_realloc(t, t->commands,
1580 struct dcerpc_sec_vt,
1581 t->count.count + 1);
1582 if (t->commands == NULL) {
1583 return NT_STATUS_NO_MEMORY;
1585 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1586 .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
1587 .u.pcontext.abstract_syntax =
1588 state->cli->table->syntax_id,
1589 .u.pcontext.transfer_syntax =
1590 state->cli->transfer_syntax,
1592 state->verify_pcontext = true;
1595 if (!a->hdr_signing) {
1596 t->commands = talloc_realloc(t, t->commands,
1597 struct dcerpc_sec_vt,
1598 t->count.count + 1);
1599 if (t->commands == NULL) {
1600 return NT_STATUS_NO_MEMORY;
1602 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1603 .command = DCERPC_SEC_VT_COMMAND_HEADER2,
1604 .u.header2.ptype = DCERPC_PKT_REQUEST,
1605 .u.header2.drep[0] = DCERPC_DREP_LE,
1606 .u.header2.call_id = state->call_id,
1607 .u.header2.context_id = state->cli->pres_context_id,
1608 .u.header2.opnum = state->op_num,
1612 if (t->count.count == 0) {
1613 TALLOC_FREE(t);
1614 return NT_STATUS_OK;
1617 t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
1619 if (DEBUGLEVEL >= 10) {
1620 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1623 ndr = ndr_push_init_ctx(state);
1624 if (ndr == NULL) {
1625 return NT_STATUS_NO_MEMORY;
1628 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1629 NDR_SCALARS | NDR_BUFFERS,
1631 TALLOC_FREE(t);
1632 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1633 return ndr_map_error2ntstatus(ndr_err);
1635 state->req_trailer = ndr_push_blob(ndr);
1637 align = state->req_data->length & 0x3;
1638 if (align > 0) {
1639 pad = 4 - align;
1641 if (pad > 0) {
1642 bool ok;
1643 uint8_t *p;
1644 const uint8_t zeros[4] = { 0, };
1646 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1647 if (!ok) {
1648 return NT_STATUS_NO_MEMORY;
1651 /* move the padding to the start */
1652 p = state->req_trailer.data;
1653 memmove(p + pad, p, state->req_trailer.length - pad);
1654 memset(p, 0, pad);
1657 return NT_STATUS_OK;
1660 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1661 bool *is_last_frag)
1663 size_t auth_len;
1664 size_t frag_len;
1665 uint8_t flags = 0;
1666 size_t pad_len;
1667 size_t data_left;
1668 size_t data_thistime;
1669 size_t trailer_left;
1670 size_t trailer_thistime = 0;
1671 size_t total_left;
1672 size_t total_thistime;
1673 NTSTATUS status;
1674 bool ok;
1675 union dcerpc_payload u;
1677 data_left = state->req_data->length - state->req_data_sent;
1678 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1679 total_left = data_left + trailer_left;
1680 if ((total_left < data_left) || (total_left < trailer_left)) {
1682 * overflow
1684 return NT_STATUS_INVALID_PARAMETER_MIX;
1687 status = dcerpc_guess_sizes(state->cli->auth,
1688 DCERPC_REQUEST_LENGTH, total_left,
1689 state->cli->conn->features.max_xmit_frag,
1690 &total_thistime,
1691 &frag_len, &auth_len, &pad_len);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 return status;
1696 if (state->req_data_sent == 0) {
1697 flags = DCERPC_PFC_FLAG_FIRST;
1700 if (total_thistime == total_left) {
1701 flags |= DCERPC_PFC_FLAG_LAST;
1704 data_thistime = MIN(total_thistime, data_left);
1705 if (data_thistime < total_thistime) {
1706 trailer_thistime = total_thistime - data_thistime;
1709 data_blob_free(&state->rpc_out);
1711 u = (union dcerpc_payload) {
1712 .request.alloc_hint = total_left,
1713 .request.context_id = state->cli->pres_context_id,
1714 .request.opnum = state->op_num,
1717 if (state->object_uuid) {
1718 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1719 u.request.object.object = *state->object_uuid;
1720 frag_len += ndr_size_GUID(state->object_uuid, 0);
1723 status = dcerpc_push_ncacn_packet(state,
1724 DCERPC_PKT_REQUEST,
1725 flags,
1726 auth_len,
1727 state->call_id,
1729 &state->rpc_out);
1730 if (!NT_STATUS_IS_OK(status)) {
1731 return status;
1734 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1735 * compute it right for requests because the auth trailer is missing
1736 * at this stage */
1737 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1739 if (data_thistime > 0) {
1740 /* Copy in the data. */
1741 ok = data_blob_append(NULL, &state->rpc_out,
1742 state->req_data->data + state->req_data_sent,
1743 data_thistime);
1744 if (!ok) {
1745 return NT_STATUS_NO_MEMORY;
1747 state->req_data_sent += data_thistime;
1750 if (trailer_thistime > 0) {
1751 /* Copy in the verification trailer. */
1752 ok = data_blob_append(NULL, &state->rpc_out,
1753 state->req_trailer.data + state->req_trailer_sent,
1754 trailer_thistime);
1755 if (!ok) {
1756 return NT_STATUS_NO_MEMORY;
1758 state->req_trailer_sent += trailer_thistime;
1761 switch (state->cli->auth->auth_level) {
1762 case DCERPC_AUTH_LEVEL_NONE:
1763 case DCERPC_AUTH_LEVEL_CONNECT:
1764 break;
1765 case DCERPC_AUTH_LEVEL_PACKET:
1766 case DCERPC_AUTH_LEVEL_INTEGRITY:
1767 case DCERPC_AUTH_LEVEL_PRIVACY:
1768 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1769 &state->rpc_out);
1770 if (!NT_STATUS_IS_OK(status)) {
1771 return status;
1773 break;
1774 default:
1775 return NT_STATUS_INVALID_PARAMETER;
1778 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1780 return status;
1783 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1785 struct tevent_req *req = tevent_req_callback_data(
1786 subreq, struct tevent_req);
1787 struct rpc_api_pipe_req_state *state = tevent_req_data(
1788 req, struct rpc_api_pipe_req_state);
1789 NTSTATUS status;
1790 bool is_last_frag;
1792 status = rpc_write_recv(subreq);
1793 TALLOC_FREE(subreq);
1794 if (tevent_req_nterror(req, status)) {
1795 return;
1798 status = prepare_next_frag(state, &is_last_frag);
1799 if (tevent_req_nterror(req, status)) {
1800 return;
1803 if (is_last_frag) {
1804 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1805 &state->rpc_out,
1806 DCERPC_PKT_RESPONSE,
1807 state->call_id);
1808 if (tevent_req_nomem(subreq, req)) {
1809 return;
1811 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1812 } else {
1813 subreq = rpc_write_send(state, state->ev,
1814 state->cli->conn->transport,
1815 state->rpc_out.data,
1816 state->rpc_out.length);
1817 if (tevent_req_nomem(subreq, req)) {
1818 return;
1820 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1821 req);
1825 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1827 struct tevent_req *req = tevent_req_callback_data(
1828 subreq, struct tevent_req);
1829 struct rpc_api_pipe_req_state *state = tevent_req_data(
1830 req, struct rpc_api_pipe_req_state);
1831 NTSTATUS status;
1833 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1834 TALLOC_FREE(subreq);
1835 if (tevent_req_nterror(req, status)) {
1836 return;
1839 if (state->cli->auth == NULL) {
1840 tevent_req_done(req);
1841 return;
1844 if (state->verify_bitmask1) {
1845 state->cli->auth->verified_bitmask1 = true;
1848 if (state->verify_pcontext) {
1849 state->cli->verified_pcontext = true;
1852 tevent_req_done(req);
1855 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1856 DATA_BLOB *reply_pdu)
1858 struct rpc_api_pipe_req_state *state = tevent_req_data(
1859 req, struct rpc_api_pipe_req_state);
1860 NTSTATUS status;
1862 if (tevent_req_is_nterror(req, &status)) {
1864 * We always have to initialize to reply pdu, even if there is
1865 * none. The rpccli_* caller routines expect this.
1867 *reply_pdu = data_blob_null;
1868 return status;
1871 /* return data to caller and assign it ownership of memory */
1872 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1873 reply_pdu->length = state->reply_pdu.length;
1874 state->reply_pdu.length = 0;
1876 return NT_STATUS_OK;
1879 /****************************************************************************
1880 Check the rpc bind acknowledge response.
1881 ****************************************************************************/
1883 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1884 struct rpc_pipe_client *cli)
1886 const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
1887 uint32_t assoc_group_id =
1888 dcerpc_binding_get_assoc_group_id(cli->assoc->binding);
1889 struct dcerpc_ack_ctx ctx;
1890 bool equal;
1892 if (r->secondary_address_size == 0) {
1893 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
1896 if (assoc_group_id == 0) {
1897 NTSTATUS status;
1900 * We only capture the first assoc_group_id we're
1901 * getting.
1903 * Current samba releases may ignore the client value
1904 * and return a different assoc_group_id if the
1905 * client given one is not found in the preforked
1906 * process. This applies to the source4 netlogon,
1907 * which uses DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED.
1910 status = dcerpc_binding_set_assoc_group_id(cli->assoc->binding,
1911 r->assoc_group_id);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 return false;
1917 if (!cli->conn->features.bind_done) {
1919 * DCE-RPC 1.1 (c706) specifies
1920 * CONST_MUST_RCV_FRAG_SIZE as 1432
1923 if (r->max_xmit_frag < 1432) {
1924 return false;
1926 if (r->max_recv_frag < 1432) {
1927 return false;
1930 cli->conn->features.max_xmit_frag =
1931 MIN(cli->conn->features.max_xmit_frag, r->max_xmit_frag);
1932 cli->conn->features.max_recv_frag =
1933 MIN(cli->conn->features.max_recv_frag, r->max_recv_frag);
1935 cli->conn->features.bind_done = true;
1938 if (r->num_results < 1 || !r->ctx_list) {
1939 return false;
1942 ctx = r->ctx_list[0];
1944 /* check the transfer syntax */
1945 equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
1946 if (!equal) {
1947 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1948 return False;
1951 if (ctx.result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1952 DBG_NOTICE("bind denied result: %d reason: %x\n",
1953 ctx.result, ctx.reason.value);
1954 return false;
1957 if (r->num_results >= 2) {
1958 const struct dcerpc_ack_ctx *neg = &r->ctx_list[1];
1960 if (neg->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1961 cli->assoc->features.negotiated = neg->reason.negotiate;
1962 cli->assoc->features.negotiation_done = true;
1964 * consume presentation context used for bind time
1965 * feature negotiation
1967 cli->conn->next_pres_context_id++;
1968 } else {
1969 DBG_DEBUG("bind_time_feature failed - "
1970 "result: %d reason %x\n",
1971 neg->result, neg->reason.value);
1975 DEBUG(5,("check_bind_response: accepted!\n"));
1976 return True;
1979 /*******************************************************************
1980 Creates a DCE/RPC bind authentication response.
1981 This is the packet that is sent back to the server once we
1982 have received a BIND-ACK, to finish the third leg of
1983 the authentication handshake.
1984 ********************************************************************/
1986 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1987 struct rpc_pipe_client *cli,
1988 struct pipe_auth_data *auth,
1989 uint32_t rpc_call_id,
1990 DATA_BLOB *pauth_blob,
1991 DATA_BLOB *rpc_out)
1993 NTSTATUS status;
1994 union dcerpc_payload u = { .auth3._pad = 0, };
1996 status = dcerpc_push_dcerpc_auth(mem_ctx,
1997 auth->auth_type,
1998 auth->auth_level,
1999 0, /* auth_pad_length */
2000 auth->auth_context_id,
2001 pauth_blob,
2002 &u.auth3.auth_info);
2003 if (!NT_STATUS_IS_OK(status)) {
2004 return status;
2007 status = dcerpc_push_ncacn_packet(mem_ctx,
2008 DCERPC_PKT_AUTH3,
2009 DCERPC_PFC_FLAG_FIRST |
2010 DCERPC_PFC_FLAG_LAST,
2011 pauth_blob->length,
2012 rpc_call_id,
2014 rpc_out);
2015 data_blob_free(&u.auth3.auth_info);
2016 if (!NT_STATUS_IS_OK(status)) {
2017 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2018 return status;
2021 return NT_STATUS_OK;
2024 /*******************************************************************
2025 Creates a DCE/RPC bind alter context authentication request which
2026 may contain a spnego auth blob
2027 ********************************************************************/
2029 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2030 struct pipe_auth_data *auth,
2031 uint32_t rpc_call_id,
2032 struct rpc_client_association *assoc,
2033 struct rpc_client_connection *conn,
2034 uint16_t pres_context_id,
2035 const struct ndr_syntax_id *abstract,
2036 const struct ndr_syntax_id *transfer,
2037 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2038 DATA_BLOB *rpc_out)
2040 DATA_BLOB auth_info;
2041 NTSTATUS status;
2043 status = dcerpc_push_dcerpc_auth(mem_ctx,
2044 auth->auth_type,
2045 auth->auth_level,
2046 0, /* auth_pad_length */
2047 auth->auth_context_id,
2048 pauth_blob,
2049 &auth_info);
2050 if (!NT_STATUS_IS_OK(status)) {
2051 return status;
2054 status = create_bind_or_alt_ctx_internal(mem_ctx,
2055 DCERPC_PKT_ALTER,
2056 rpc_call_id,
2057 assoc,
2058 conn,
2059 pres_context_id,
2060 abstract,
2061 transfer,
2062 &auth_info,
2063 rpc_out);
2064 data_blob_free(&auth_info);
2065 return status;
2068 /****************************************************************************
2069 Do an rpc bind.
2070 ****************************************************************************/
2072 struct rpc_pipe_bind_state {
2073 struct tevent_context *ev;
2074 struct rpc_pipe_client *cli;
2075 DATA_BLOB rpc_out;
2076 bool auth3;
2077 uint32_t rpc_call_id;
2080 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2081 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2082 struct rpc_pipe_bind_state *state,
2083 DATA_BLOB *credentials);
2084 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2085 struct rpc_pipe_bind_state *state,
2086 DATA_BLOB *credentials);
2088 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2089 struct tevent_context *ev,
2090 struct rpc_pipe_client *cli,
2091 struct pipe_auth_data *auth)
2093 struct tevent_req *req, *subreq;
2094 struct rpc_pipe_bind_state *state;
2095 struct cli_credentials *creds = NULL;
2096 const char *username = NULL;
2097 enum dcerpc_pkt_type rep_ptype = DCERPC_PKT_BIND_ACK;
2098 NTSTATUS status;
2100 if (cli->conn->features.bind_done) {
2101 rep_ptype = DCERPC_PKT_ALTER_RESP;
2104 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2105 if (req == NULL) {
2106 return NULL;
2109 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2110 rpccli_pipe_txt(talloc_tos(), cli),
2111 (unsigned int)auth->auth_type,
2112 (unsigned int)auth->auth_level ));
2114 state->ev = ev;
2115 state->cli = cli;
2116 state->rpc_call_id = ++cli->assoc->next_call_id;
2118 cli->auth = talloc_move(cli, &auth);
2119 if (cli->auth->auth_context_id == UINT32_MAX) {
2120 if (cli->conn->next_auth_context_id == UINT32_MAX) {
2121 tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
2122 return tevent_req_post(req, ev);
2124 cli->auth->auth_context_id = cli->conn->next_auth_context_id++;
2126 if (cli->pres_context_id == UINT16_MAX) {
2127 if (cli->conn->next_pres_context_id == UINT16_MAX) {
2128 tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
2129 return tevent_req_post(req, ev);
2131 cli->pres_context_id = cli->conn->next_pres_context_id++;
2134 cli->binding_handle = rpccli_bh_create(cli, NULL, cli->table);
2135 if (tevent_req_nomem(cli->binding_handle, req)) {
2136 return tevent_req_post(req, ev);
2139 creds = gensec_get_credentials(cli->auth->auth_ctx);
2140 username = cli_credentials_get_username(creds);
2141 cli->printer_username = talloc_strdup(cli, username);
2142 if (tevent_req_nomem(cli->printer_username, req)) {
2143 return tevent_req_post(req, ev);
2146 /* Marshall the outgoing data. */
2147 status = create_rpc_bind_req(state, cli,
2148 cli->auth,
2149 state->rpc_call_id,
2150 &cli->table->syntax_id,
2151 &cli->transfer_syntax,
2152 &state->rpc_out);
2154 if (!NT_STATUS_IS_OK(status) &&
2155 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2156 tevent_req_nterror(req, status);
2157 return tevent_req_post(req, ev);
2160 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2161 rep_ptype, state->rpc_call_id);
2162 if (tevent_req_nomem(subreq, req)) {
2163 return tevent_req_post(req, ev);
2165 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2166 return req;
2169 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2171 struct tevent_req *req = tevent_req_callback_data(
2172 subreq, struct tevent_req);
2173 struct rpc_pipe_bind_state *state = tevent_req_data(
2174 req, struct rpc_pipe_bind_state);
2175 struct pipe_auth_data *pauth = state->cli->auth;
2176 struct gensec_security *gensec_security;
2177 struct ncacn_packet *pkt = NULL;
2178 struct dcerpc_auth auth;
2179 DATA_BLOB auth_token = { .data = NULL };
2180 NTSTATUS status;
2182 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2183 TALLOC_FREE(subreq);
2184 if (tevent_req_nterror(req, status)) {
2185 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2186 rpccli_pipe_txt(talloc_tos(), state->cli),
2187 nt_errstr(status)));
2188 return;
2191 if (state->auth3) {
2192 tevent_req_done(req);
2193 return;
2196 if (!check_bind_response(&pkt->u.bind_ack, state->cli)) {
2197 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2198 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2199 return;
2202 if (state->cli->conn->features.client_hdr_signing &&
2203 pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
2205 state->cli->conn->features.hdr_signing = true;
2208 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2209 /* Bind complete. */
2210 tevent_req_done(req);
2211 return;
2214 if (pkt->auth_length == 0) {
2215 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2216 return;
2219 pauth->hdr_signing = state->cli->conn->features.hdr_signing;
2221 /* get auth credentials */
2222 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
2223 &pkt->u.bind_ack.auth_info,
2224 &auth, NULL, true);
2225 if (tevent_req_nterror(req, status)) {
2226 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2227 nt_errstr(status)));
2228 return;
2231 if (auth.auth_type != pauth->auth_type) {
2232 DBG_ERR("Auth type %u mismatch expected %u.\n",
2233 auth.auth_type, pauth->auth_type);
2234 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2235 return;
2238 if (auth.auth_level != pauth->auth_level) {
2239 DBG_ERR("Auth level %u mismatch expected %u.\n",
2240 auth.auth_level, pauth->auth_level);
2241 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2242 return;
2245 if (auth.auth_context_id != pauth->auth_context_id) {
2246 DBG_ERR("Auth context id %"PRIu32" mismatch "
2247 "expected %"PRIu32".\n",
2248 auth.auth_context_id,
2249 pauth->auth_context_id);
2250 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2251 return;
2255 * For authenticated binds we may need to do 3 or 4 leg binds.
2258 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2259 /* Bind complete. */
2260 tevent_req_done(req);
2261 return;
2264 gensec_security = pauth->auth_ctx;
2266 status = gensec_update(gensec_security, state,
2267 auth.credentials, &auth_token);
2268 if (NT_STATUS_EQUAL(status,
2269 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2270 status = rpc_bind_next_send(req, state,
2271 &auth_token);
2272 } else if (NT_STATUS_IS_OK(status)) {
2273 if (pauth->hdr_signing) {
2274 gensec_want_feature(gensec_security,
2275 GENSEC_FEATURE_SIGN_PKT_HEADER);
2278 if (auth_token.length == 0) {
2279 /* Bind complete. */
2280 tevent_req_done(req);
2281 return;
2283 status = rpc_bind_finish_send(req, state,
2284 &auth_token);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 tevent_req_nterror(req, status);
2290 return;
2293 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2294 struct rpc_pipe_bind_state *state,
2295 DATA_BLOB *auth_token)
2297 struct pipe_auth_data *auth = state->cli->auth;
2298 struct tevent_req *subreq;
2299 NTSTATUS status;
2301 /* Now prepare the alter context pdu. */
2302 data_blob_free(&state->rpc_out);
2304 status = create_rpc_alter_context(state, auth,
2305 state->rpc_call_id,
2306 state->cli->assoc,
2307 state->cli->conn,
2308 state->cli->pres_context_id,
2309 &state->cli->table->syntax_id,
2310 &state->cli->transfer_syntax,
2311 auth_token,
2312 &state->rpc_out);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 return status;
2317 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2318 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2319 state->rpc_call_id);
2320 if (subreq == NULL) {
2321 return NT_STATUS_NO_MEMORY;
2323 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2324 return NT_STATUS_OK;
2327 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2328 struct rpc_pipe_bind_state *state,
2329 DATA_BLOB *auth_token)
2331 struct pipe_auth_data *auth = state->cli->auth;
2332 struct tevent_req *subreq;
2333 NTSTATUS status;
2335 state->auth3 = true;
2337 /* Now prepare the auth3 context pdu. */
2338 data_blob_free(&state->rpc_out);
2340 status = create_rpc_bind_auth3(state, state->cli, auth,
2341 state->rpc_call_id,
2342 auth_token,
2343 &state->rpc_out);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 return status;
2348 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2349 &state->rpc_out, DCERPC_PKT_AUTH3,
2350 state->rpc_call_id);
2351 if (subreq == NULL) {
2352 return NT_STATUS_NO_MEMORY;
2354 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2355 return NT_STATUS_OK;
2358 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2360 return tevent_req_simple_recv_ntstatus(req);
2363 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2364 struct pipe_auth_data *auth)
2366 TALLOC_CTX *frame = talloc_stackframe();
2367 struct tevent_context *ev;
2368 struct tevent_req *req;
2369 NTSTATUS status = NT_STATUS_OK;
2371 ev = samba_tevent_context_init(frame);
2372 if (ev == NULL) {
2373 status = NT_STATUS_NO_MEMORY;
2374 goto fail;
2377 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2378 if (req == NULL) {
2379 status = NT_STATUS_NO_MEMORY;
2380 goto fail;
2383 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2384 goto fail;
2387 status = rpc_pipe_bind_recv(req);
2388 fail:
2389 TALLOC_FREE(frame);
2390 return status;
2393 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2395 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2396 unsigned int timeout)
2398 if (rpc_cli == NULL) {
2399 return RPCCLI_DEFAULT_TIMEOUT;
2402 if (rpc_cli->binding_handle == NULL) {
2403 return RPCCLI_DEFAULT_TIMEOUT;
2406 return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2407 timeout);
2410 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2412 if (rpc_cli == NULL) {
2413 return false;
2416 if (rpc_cli->binding_handle == NULL) {
2417 return false;
2420 return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2423 struct rpccli_bh_state {
2424 struct rpc_pipe_client *rpc_cli;
2425 struct dcerpc_binding *binding;
2428 static const struct dcerpc_binding *rpccli_bh_get_binding(struct dcerpc_binding_handle *h)
2430 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2431 struct rpccli_bh_state);
2433 return hs->binding;
2436 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2438 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2439 struct rpccli_bh_state);
2440 struct rpc_cli_transport *transport = NULL;
2442 if (hs->rpc_cli == NULL) {
2443 return false;
2446 if (hs->rpc_cli->conn == NULL) {
2447 return false;
2450 transport = hs->rpc_cli->conn->transport;
2451 if (transport == NULL) {
2452 return false;
2455 if (transport->is_connected == NULL) {
2456 return false;
2459 return transport->is_connected(transport->priv);
2462 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2463 uint32_t timeout)
2465 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2466 struct rpccli_bh_state);
2467 struct rpc_cli_transport *transport = NULL;
2468 unsigned int old;
2470 if (hs->rpc_cli->conn == NULL) {
2471 return RPCCLI_DEFAULT_TIMEOUT;
2474 transport = hs->rpc_cli->conn->transport;
2475 if (transport == NULL) {
2476 return RPCCLI_DEFAULT_TIMEOUT;
2479 if (transport->set_timeout == NULL) {
2480 return RPCCLI_DEFAULT_TIMEOUT;
2483 old = transport->set_timeout(transport->priv, timeout);
2484 if (old == 0) {
2485 return RPCCLI_DEFAULT_TIMEOUT;
2488 return old;
2491 static NTSTATUS rpccli_bh_transport_session_key(struct dcerpc_binding_handle *h,
2492 TALLOC_CTX *mem_ctx,
2493 DATA_BLOB *session_key)
2495 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2496 struct rpccli_bh_state);
2497 DATA_BLOB sk = { .length = 0, };
2499 if (hs->rpc_cli == NULL) {
2500 return NT_STATUS_NO_USER_SESSION_KEY;
2503 if (hs->rpc_cli->conn == NULL) {
2504 return NT_STATUS_NO_USER_SESSION_KEY;
2507 if (hs->rpc_cli->conn->transport_session_key.length == 0) {
2508 return NT_STATUS_NO_USER_SESSION_KEY;
2511 sk = hs->rpc_cli->conn->transport_session_key;
2512 sk.length = MIN(sk.length, 16);
2514 *session_key = data_blob_dup_talloc(mem_ctx, sk);
2515 if (session_key->length != sk.length) {
2516 return NT_STATUS_NO_MEMORY;
2518 talloc_keep_secret(session_key->data);
2519 return NT_STATUS_OK;
2522 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2523 enum dcerpc_AuthType *auth_type,
2524 enum dcerpc_AuthLevel *auth_level)
2526 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2527 struct rpccli_bh_state);
2529 if (hs->rpc_cli == NULL) {
2530 return;
2533 if (hs->rpc_cli->auth == NULL) {
2534 return;
2537 *auth_type = hs->rpc_cli->auth->auth_type;
2538 *auth_level = hs->rpc_cli->auth->auth_level;
2541 static NTSTATUS rpccli_bh_auth_session_key(struct dcerpc_binding_handle *h,
2542 TALLOC_CTX *mem_ctx,
2543 DATA_BLOB *session_key)
2545 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2546 struct rpccli_bh_state);
2547 struct pipe_auth_data *auth = NULL;
2548 NTSTATUS status;
2550 if (hs->rpc_cli == NULL) {
2551 return NT_STATUS_NO_USER_SESSION_KEY;
2554 if (hs->rpc_cli->auth == NULL) {
2555 return NT_STATUS_NO_USER_SESSION_KEY;
2558 auth = hs->rpc_cli->auth;
2560 if (auth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2561 return NT_STATUS_NO_USER_SESSION_KEY;
2564 if (auth->auth_ctx == NULL) {
2565 return NT_STATUS_NO_USER_SESSION_KEY;
2568 status = gensec_session_key(auth->auth_ctx,
2569 mem_ctx,
2570 session_key);
2571 if (!NT_STATUS_IS_OK(status)) {
2572 return status;
2575 talloc_keep_secret(session_key->data);
2576 return NT_STATUS_OK;
2579 struct rpccli_bh_raw_call_state {
2580 DATA_BLOB in_data;
2581 DATA_BLOB out_data;
2582 uint32_t out_flags;
2585 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2587 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2588 struct tevent_context *ev,
2589 struct dcerpc_binding_handle *h,
2590 const struct GUID *object,
2591 uint32_t opnum,
2592 uint32_t in_flags,
2593 const uint8_t *in_data,
2594 size_t in_length)
2596 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2597 struct rpccli_bh_state);
2598 struct tevent_req *req;
2599 struct rpccli_bh_raw_call_state *state;
2600 bool ok;
2601 struct tevent_req *subreq;
2603 req = tevent_req_create(mem_ctx, &state,
2604 struct rpccli_bh_raw_call_state);
2605 if (req == NULL) {
2606 return NULL;
2608 state->in_data.data = discard_const_p(uint8_t, in_data);
2609 state->in_data.length = in_length;
2611 ok = rpccli_bh_is_connected(h);
2612 if (!ok) {
2613 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2614 return tevent_req_post(req, ev);
2617 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2618 opnum, object, &state->in_data);
2619 if (tevent_req_nomem(subreq, req)) {
2620 return tevent_req_post(req, ev);
2622 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2624 return req;
2627 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2629 struct tevent_req *req =
2630 tevent_req_callback_data(subreq,
2631 struct tevent_req);
2632 struct rpccli_bh_raw_call_state *state =
2633 tevent_req_data(req,
2634 struct rpccli_bh_raw_call_state);
2635 NTSTATUS status;
2637 state->out_flags = 0;
2639 /* TODO: support bigendian responses */
2641 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2642 TALLOC_FREE(subreq);
2643 if (tevent_req_nterror(req, status)) {
2644 return;
2647 tevent_req_done(req);
2650 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2651 TALLOC_CTX *mem_ctx,
2652 uint8_t **out_data,
2653 size_t *out_length,
2654 uint32_t *out_flags)
2656 struct rpccli_bh_raw_call_state *state =
2657 tevent_req_data(req,
2658 struct rpccli_bh_raw_call_state);
2659 NTSTATUS status;
2661 if (tevent_req_is_nterror(req, &status)) {
2662 tevent_req_received(req);
2663 return status;
2666 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2667 *out_length = state->out_data.length;
2668 *out_flags = state->out_flags;
2669 tevent_req_received(req);
2670 return NT_STATUS_OK;
2673 struct rpccli_bh_disconnect_state {
2674 uint8_t _dummy;
2677 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2678 struct tevent_context *ev,
2679 struct dcerpc_binding_handle *h)
2681 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2682 struct rpccli_bh_state);
2683 struct tevent_req *req;
2684 struct rpccli_bh_disconnect_state *state;
2685 bool ok;
2687 req = tevent_req_create(mem_ctx, &state,
2688 struct rpccli_bh_disconnect_state);
2689 if (req == NULL) {
2690 return NULL;
2693 ok = rpccli_bh_is_connected(h);
2694 if (!ok) {
2695 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2696 return tevent_req_post(req, ev);
2700 * TODO: do a real async disconnect ...
2702 * For now we do it sync...
2704 TALLOC_FREE(hs->rpc_cli->conn);
2705 hs->rpc_cli = NULL;
2707 tevent_req_done(req);
2708 return tevent_req_post(req, ev);
2711 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2713 return tevent_req_simple_recv_ntstatus(req);
2716 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2718 return true;
2721 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2722 ndr_flags_type ndr_flags,
2723 const void *_struct_ptr,
2724 const struct ndr_interface_call *call)
2726 void *struct_ptr = discard_const(_struct_ptr);
2728 if (DEBUGLEVEL < 10) {
2729 return;
2732 if (ndr_flags & NDR_IN) {
2733 ndr_print_function_debug(call->ndr_print,
2734 call->name,
2735 ndr_flags,
2736 struct_ptr);
2738 if (ndr_flags & NDR_OUT) {
2739 ndr_print_function_debug(call->ndr_print,
2740 call->name,
2741 ndr_flags,
2742 struct_ptr);
2746 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2747 .name = "rpccli",
2748 .get_binding = rpccli_bh_get_binding,
2749 .is_connected = rpccli_bh_is_connected,
2750 .set_timeout = rpccli_bh_set_timeout,
2751 .transport_session_key = rpccli_bh_transport_session_key,
2752 .auth_info = rpccli_bh_auth_info,
2753 .auth_session_key = rpccli_bh_auth_session_key,
2754 .raw_call_send = rpccli_bh_raw_call_send,
2755 .raw_call_recv = rpccli_bh_raw_call_recv,
2756 .disconnect_send = rpccli_bh_disconnect_send,
2757 .disconnect_recv = rpccli_bh_disconnect_recv,
2759 .ref_alloc = rpccli_bh_ref_alloc,
2760 .do_ndr_print = rpccli_bh_do_ndr_print,
2763 /* initialise a rpc_pipe_client binding handle */
2764 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2765 const struct GUID *object,
2766 const struct ndr_interface_table *table)
2768 struct dcerpc_binding_handle *h = NULL;
2769 struct rpccli_bh_state *hs = NULL;
2770 struct dcerpc_binding *b = NULL;
2771 char localaddr[INET6_ADDRSTRLEN] = { 0, };
2772 uint32_t a_flags = 0;
2773 uint32_t c_flags = 0;
2774 NTSTATUS status;
2776 if (c->conn->features.hdr_signing) {
2777 a_flags |= DCERPC_HEADER_SIGNING;
2778 } else {
2779 c_flags |= DCERPC_HEADER_SIGNING;
2782 switch (c->auth->auth_type) {
2783 case DCERPC_AUTH_TYPE_KRB5:
2784 a_flags |= DCERPC_AUTH_KRB5;
2785 c_flags |= DCERPC_AUTH_NTLM;
2786 c_flags |= DCERPC_AUTH_SPNEGO;
2787 c_flags |= DCERPC_SCHANNEL;
2788 break;
2789 case DCERPC_AUTH_TYPE_NTLMSSP:
2790 c_flags |= DCERPC_AUTH_KRB5;
2791 a_flags |= DCERPC_AUTH_NTLM;
2792 c_flags |= DCERPC_AUTH_SPNEGO;
2793 c_flags |= DCERPC_SCHANNEL;
2794 break;
2795 case DCERPC_AUTH_TYPE_SPNEGO:
2796 c_flags |= DCERPC_AUTH_KRB5;
2797 c_flags |= DCERPC_AUTH_NTLM;
2798 a_flags |= DCERPC_AUTH_SPNEGO;
2799 c_flags |= DCERPC_SCHANNEL;
2800 break;
2801 case DCERPC_AUTH_TYPE_SCHANNEL:
2802 c_flags |= DCERPC_AUTH_KRB5;
2803 c_flags |= DCERPC_AUTH_NTLM;
2804 c_flags |= DCERPC_AUTH_SPNEGO;
2805 a_flags |= DCERPC_SCHANNEL;
2806 break;
2807 default:
2808 c_flags |= DCERPC_AUTH_KRB5;
2809 c_flags |= DCERPC_AUTH_NTLM;
2810 c_flags |= DCERPC_AUTH_SPNEGO;
2811 c_flags |= DCERPC_SCHANNEL;
2812 break;
2815 if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_PRIVACY) {
2816 a_flags |= DCERPC_SEAL;
2817 c_flags |= DCERPC_SIGN;
2818 c_flags |= DCERPC_CONNECT;
2819 } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2820 c_flags |= DCERPC_SEAL;
2821 a_flags |= DCERPC_SIGN;
2822 c_flags |= DCERPC_CONNECT;
2823 } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_CONNECT) {
2824 c_flags |= DCERPC_SEAL;
2825 c_flags |= DCERPC_SIGN;
2826 a_flags |= DCERPC_CONNECT;
2827 } else {
2828 c_flags |= DCERPC_SEAL;
2829 c_flags |= DCERPC_SIGN;
2830 c_flags |= DCERPC_CONNECT;
2833 h = dcerpc_binding_handle_create(c,
2834 &rpccli_bh_ops,
2835 object,
2836 table,
2837 &hs,
2838 struct rpccli_bh_state,
2839 __location__);
2840 if (h == NULL) {
2841 return NULL;
2843 hs->rpc_cli = c;
2845 b = dcerpc_binding_dup(h, c->assoc->binding);
2846 if (b == NULL) {
2847 TALLOC_FREE(h);
2848 return NULL;
2850 status = dcerpc_binding_set_abstract_syntax(b, &table->syntax_id);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 TALLOC_FREE(h);
2853 return NULL;
2855 status = dcerpc_binding_set_flags(b, a_flags, c_flags);
2856 if (!NT_STATUS_IS_OK(status)) {
2857 TALLOC_FREE(h);
2858 return NULL;
2861 switch (c->conn->localaddr.u.sa.sa_family) {
2862 case AF_INET:
2863 case AF_INET6:
2864 print_sockaddr(localaddr,
2865 sizeof(localaddr),
2866 &c->conn->localaddr.u.ss);
2867 status = dcerpc_binding_set_string_option(b,
2868 "localaddress",
2869 localaddr);
2870 if (!NT_STATUS_IS_OK(status)) {
2871 TALLOC_FREE(h);
2872 return NULL;
2874 break;
2877 hs->binding = b;
2879 return h;
2882 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2883 struct pipe_auth_data **presult)
2885 struct pipe_auth_data *result;
2886 struct auth_generic_state *auth_generic_ctx;
2887 NTSTATUS status;
2889 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2890 if (result == NULL) {
2891 return NT_STATUS_NO_MEMORY;
2894 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2895 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2896 /* rpc_pipe_bind_send should allocate an id... */
2897 result->auth_context_id = UINT32_MAX;
2899 status = auth_generic_client_prepare(result,
2900 &auth_generic_ctx);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2903 nt_errstr(status)));
2906 status = auth_generic_set_username(auth_generic_ctx, "");
2907 if (!NT_STATUS_IS_OK(status)) {
2908 DEBUG(1, ("Failed to set username: %s\n",
2909 nt_errstr(status)));
2912 status = auth_generic_set_domain(auth_generic_ctx, "");
2913 if (!NT_STATUS_IS_OK(status)) {
2914 DEBUG(1, ("Failed to set domain: %s\n",
2915 nt_errstr(status)));
2916 return status;
2919 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2920 auth_generic_ctx->credentials);
2921 if (!NT_STATUS_IS_OK(status)) {
2922 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2923 nt_errstr(status)));
2924 return status;
2926 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2927 auth_generic_ctx->credentials = NULL;
2929 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2930 talloc_free(auth_generic_ctx);
2931 *presult = result;
2932 return NT_STATUS_OK;
2935 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2936 enum dcerpc_AuthType auth_type,
2937 enum dcerpc_AuthLevel auth_level,
2938 const char *server,
2939 const char *target_service,
2940 const char *domain,
2941 const char *username,
2942 const char *password,
2943 enum credentials_use_kerberos use_kerberos,
2944 struct netlogon_creds_CredentialState *creds,
2945 struct pipe_auth_data **presult)
2947 struct auth_generic_state *auth_generic_ctx;
2948 struct pipe_auth_data *result;
2949 NTSTATUS status;
2951 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2952 if (result == NULL) {
2953 return NT_STATUS_NO_MEMORY;
2956 result->auth_type = auth_type;
2957 result->auth_level = auth_level;
2958 /* rpc_pipe_bind_send should allocate an id... */
2959 result->auth_context_id = UINT32_MAX;
2961 status = auth_generic_client_prepare(result,
2962 &auth_generic_ctx);
2963 if (!NT_STATUS_IS_OK(status)) {
2964 goto fail;
2967 status = auth_generic_set_username(auth_generic_ctx, username);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 goto fail;
2972 status = auth_generic_set_domain(auth_generic_ctx, domain);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 goto fail;
2977 status = auth_generic_set_password(auth_generic_ctx, password);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 goto fail;
2982 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 goto fail;
2987 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2988 if (!NT_STATUS_IS_OK(status)) {
2989 goto fail;
2992 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
2993 use_kerberos,
2994 CRED_SPECIFIED);
2995 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2997 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2998 if (!NT_STATUS_IS_OK(status)) {
2999 goto fail;
3002 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
3003 talloc_free(auth_generic_ctx);
3004 *presult = result;
3005 return NT_STATUS_OK;
3007 fail:
3008 TALLOC_FREE(result);
3009 return status;
3012 /* This routine steals the creds pointer that is passed in */
3013 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
3014 enum dcerpc_AuthType auth_type,
3015 enum dcerpc_AuthLevel auth_level,
3016 const char *server,
3017 const char *target_service,
3018 struct cli_credentials *creds,
3019 struct pipe_auth_data **presult)
3021 struct auth_generic_state *auth_generic_ctx;
3022 struct pipe_auth_data *result;
3023 NTSTATUS status;
3025 result = talloc_zero(mem_ctx, struct pipe_auth_data);
3026 if (result == NULL) {
3027 return NT_STATUS_NO_MEMORY;
3030 result->auth_type = auth_type;
3031 result->auth_level = auth_level;
3032 /* rpc_pipe_bind_send should allocate an id... */
3033 result->auth_context_id = UINT32_MAX;
3035 status = auth_generic_client_prepare(result,
3036 &auth_generic_ctx);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 goto fail;
3041 status = auth_generic_set_creds(auth_generic_ctx, creds);
3042 if (!NT_STATUS_IS_OK(status)) {
3043 goto fail;
3046 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 goto fail;
3051 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
3052 if (!NT_STATUS_IS_OK(status)) {
3053 goto fail;
3056 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
3057 if (!NT_STATUS_IS_OK(status)) {
3058 goto fail;
3061 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
3062 talloc_free(auth_generic_ctx);
3063 *presult = result;
3064 return NT_STATUS_OK;
3066 fail:
3067 TALLOC_FREE(result);
3068 return status;
3071 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
3072 struct pipe_auth_data **presult)
3074 return rpccli_generic_bind_data(mem_ctx,
3075 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
3076 DCERPC_AUTH_LEVEL_CONNECT,
3077 NULL, /* server */
3078 "host", /* target_service */
3079 NAME_NT_AUTHORITY, /* domain */
3080 "SYSTEM",
3081 NULL, /* password */
3082 CRED_USE_KERBEROS_DISABLED,
3083 NULL, /* netlogon_creds_CredentialState */
3084 presult);
3088 * Create an rpc pipe client struct, connecting to a tcp port.
3090 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx,
3091 const struct rpc_client_association *assoc,
3092 struct rpc_client_connection **pconn)
3094 struct rpc_client_connection *conn = NULL;
3095 enum dcerpc_transport_t transport;
3096 const char *endpoint = NULL;
3097 uint16_t port;
3098 NTSTATUS status;
3099 int fd;
3100 int ret;
3102 transport = dcerpc_binding_get_transport(assoc->binding);
3103 if (transport != NCACN_IP_TCP) {
3104 return NT_STATUS_RPC_WRONG_KIND_OF_BINDING;
3107 endpoint = dcerpc_binding_get_string_option(assoc->binding,
3108 "endpoint");
3109 if (endpoint == NULL) {
3110 return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT;
3112 port = (uint16_t)atoi(endpoint);
3113 if (port == 0) {
3114 return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT;
3117 status = rpc_client_connection_create(mem_ctx,
3118 assoc,
3119 DCERPC_FRAG_MAX_SIZE,
3120 &conn);
3121 if (!NT_STATUS_IS_OK(status)) {
3122 return status;
3125 status = open_socket_out(&assoc->addr.u.ss, port, 60*1000, &fd);
3126 if (!NT_STATUS_IS_OK(status)) {
3127 TALLOC_FREE(conn);
3128 return status;
3130 set_socket_options(fd, lp_socket_options());
3132 conn->localaddr.sa_socklen = sizeof(conn->localaddr.u.ss);
3133 ret = getsockname(fd, &conn->localaddr.u.sa, &conn->localaddr.sa_socklen);
3134 if (ret != 0) {
3135 status = map_nt_error_from_unix_common(errno);
3136 close(fd);
3137 TALLOC_FREE(conn);
3138 return status;
3141 status = rpc_transport_sock_init(conn, fd, &conn->transport);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 close(fd);
3144 TALLOC_FREE(conn);
3145 return status;
3148 conn->transport->transport = NCACN_IP_TCP;
3150 *pconn = conn;
3151 return NT_STATUS_OK;
3154 static NTSTATUS rpccli_epm_map_binding(
3155 struct dcerpc_binding_handle *epm_connection,
3156 struct dcerpc_binding *binding,
3157 TALLOC_CTX *mem_ctx,
3158 char **pendpoint)
3160 TALLOC_CTX *frame = talloc_stackframe();
3161 enum dcerpc_transport_t transport =
3162 dcerpc_binding_get_transport(binding);
3163 enum dcerpc_transport_t res_transport;
3164 struct dcerpc_binding *res_binding = NULL;
3165 struct epm_twr_t *map_tower = NULL;
3166 struct epm_twr_p_t res_towers = { .twr = NULL };
3167 struct policy_handle *entry_handle = NULL;
3168 uint32_t num_towers = 0;
3169 const uint32_t max_towers = 1;
3170 const char *endpoint = NULL;
3171 char *tmp = NULL;
3172 uint32_t result;
3173 NTSTATUS status;
3175 map_tower = talloc_zero(frame, struct epm_twr_t);
3176 if (map_tower == NULL) {
3177 goto nomem;
3180 status = dcerpc_binding_build_tower(
3181 frame, binding, &(map_tower->tower));
3182 if (!NT_STATUS_IS_OK(status)) {
3183 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
3184 nt_errstr(status));
3185 goto done;
3188 res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
3189 if (res_towers.twr == NULL) {
3190 goto nomem;
3193 entry_handle = talloc_zero(frame, struct policy_handle);
3194 if (entry_handle == NULL) {
3195 goto nomem;
3198 status = dcerpc_epm_Map(
3199 epm_connection,
3200 frame,
3201 NULL,
3202 map_tower,
3203 entry_handle,
3204 max_towers,
3205 &num_towers,
3206 &res_towers,
3207 &result);
3209 if (!NT_STATUS_IS_OK(status)) {
3210 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
3211 goto done;
3214 if (result != EPMAPPER_STATUS_OK) {
3215 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
3216 status = NT_STATUS_NOT_FOUND;
3217 goto done;
3220 if (num_towers != 1) {
3221 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
3222 num_towers);
3223 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3224 goto done;
3227 status = dcerpc_binding_from_tower(
3228 frame, &(res_towers.twr->tower), &res_binding);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
3231 nt_errstr(status));
3232 goto done;
3235 res_transport = dcerpc_binding_get_transport(res_binding);
3236 if (res_transport != transport) {
3237 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
3238 "expected %d\n",
3239 (int)res_transport,
3240 (int)transport);
3241 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3242 goto done;
3245 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
3246 if (endpoint == NULL) {
3247 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
3248 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3249 goto done;
3252 tmp = talloc_strdup(mem_ctx, endpoint);
3253 if (tmp == NULL) {
3254 goto nomem;
3256 *pendpoint = tmp;
3258 status = NT_STATUS_OK;
3259 goto done;
3261 nomem:
3262 status = NT_STATUS_NO_MEMORY;
3263 done:
3264 TALLOC_FREE(frame);
3265 return status;
3268 static NTSTATUS rpccli_epm_map_interface(
3269 struct dcerpc_binding_handle *epm_connection,
3270 enum dcerpc_transport_t transport,
3271 const struct ndr_syntax_id *iface,
3272 TALLOC_CTX *mem_ctx,
3273 char **pendpoint)
3275 struct dcerpc_binding *binding = NULL;
3276 char *endpoint = NULL;
3277 NTSTATUS status;
3279 status = dcerpc_parse_binding(mem_ctx, "", &binding);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
3282 nt_errstr(status));
3283 goto done;
3286 status = dcerpc_binding_set_transport(binding, transport);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
3289 nt_errstr(status));
3290 goto done;
3293 status = dcerpc_binding_set_abstract_syntax(binding, iface);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
3296 nt_errstr(status));
3297 goto done;
3300 status = rpccli_epm_map_binding(
3301 epm_connection, binding, mem_ctx, &endpoint);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
3304 nt_errstr(status));
3305 goto done;
3307 *pendpoint = endpoint;
3309 done:
3310 TALLOC_FREE(binding);
3311 return status;
3315 * Determine the tcp port on which a dcerpc interface is listening
3316 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3317 * target host.
3319 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3320 const struct samba_sockaddr *saddr,
3321 const struct ndr_interface_table *table,
3322 uint16_t *pport)
3324 TALLOC_CTX *frame = talloc_stackframe();
3325 const char *epm_ep = NULL;
3326 struct rpc_client_association *epm_assoc = NULL;
3327 struct rpc_client_connection *epm_conn = NULL;
3328 struct rpc_pipe_client *epm_pipe = NULL;
3329 struct pipe_auth_data *epm_auth = NULL;
3330 char *endpoint = NULL;
3331 uint16_t port = 0;
3332 NTSTATUS status;
3334 endpoint = dcerpc_default_transport_endpoint(frame,
3335 NCACN_IP_TCP,
3336 table);
3337 if (endpoint != NULL) {
3338 port = (uint16_t)atoi(endpoint);
3341 if (port != 0) {
3342 *pport = port;
3343 TALLOC_FREE(frame);
3344 return NT_STATUS_OK;
3347 epm_ep = dcerpc_default_transport_endpoint(frame,
3348 NCACN_IP_TCP,
3349 &ndr_table_epmapper);
3350 if (epm_ep == NULL) {
3351 TALLOC_FREE(frame);
3352 return NT_STATUS_RPC_INTERNAL_ERROR;
3355 status = rpc_client_association_create(frame,
3356 default_bt_features,
3357 DCERPC_PROPOSE_HEADER_SIGNING,
3358 host,
3359 NCACN_IP_TCP,
3360 saddr,
3361 epm_ep,
3362 &epm_assoc);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 TALLOC_FREE(frame);
3365 return status;
3368 /* open the connection to the endpoint mapper */
3369 status = rpc_pipe_open_tcp_port(frame, epm_assoc, &epm_conn);
3370 if (!NT_STATUS_IS_OK(status)) {
3371 TALLOC_FREE(frame);
3372 return status;
3375 status = rpccli_anon_bind_data(frame, &epm_auth);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 TALLOC_FREE(frame);
3378 return status;
3381 status = rpc_pipe_wrap_create(&ndr_table_epmapper,
3382 NULL,
3383 &epm_assoc,
3384 &epm_conn,
3385 frame,
3386 &epm_pipe);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 TALLOC_FREE(frame);
3389 return status;
3392 status = rpc_pipe_bind(epm_pipe, epm_auth);
3393 if (!NT_STATUS_IS_OK(status)) {
3394 TALLOC_FREE(frame);
3395 return status;
3398 status = rpccli_epm_map_interface(
3399 epm_pipe->binding_handle,
3400 NCACN_IP_TCP,
3401 &table->syntax_id,
3402 frame,
3403 &endpoint);
3404 if (!NT_STATUS_IS_OK(status)) {
3405 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3406 nt_errstr(status));
3407 TALLOC_FREE(frame);
3408 return status;
3411 *pport = (uint16_t)atoi(endpoint);
3412 TALLOC_FREE(frame);
3413 return NT_STATUS_OK;
3416 static NTSTATUS rpc_pipe_get_ncalrpc_name(
3417 const struct ndr_syntax_id *iface,
3418 TALLOC_CTX *mem_ctx,
3419 char **psocket_name)
3421 TALLOC_CTX *frame = talloc_stackframe();
3422 struct rpc_pipe_client *epm_pipe = NULL;
3423 struct pipe_auth_data *auth = NULL;
3424 NTSTATUS status = NT_STATUS_OK;
3425 bool is_epm;
3427 is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
3428 if (is_epm) {
3429 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
3430 if (endpoint == NULL) {
3431 status = NT_STATUS_NO_MEMORY;
3432 goto done;
3434 *psocket_name = endpoint;
3435 goto done;
3438 status = rpc_pipe_open_ncalrpc(
3439 frame, &ndr_table_epmapper, &epm_pipe);
3440 if (!NT_STATUS_IS_OK(status)) {
3441 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
3442 nt_errstr(status));
3443 goto done;
3446 status = rpccli_anon_bind_data(epm_pipe, &auth);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3449 nt_errstr(status));
3450 goto done;
3453 status = rpc_pipe_bind(epm_pipe, auth);
3454 if (!NT_STATUS_IS_OK(status)) {
3455 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3456 goto done;
3459 status = rpccli_epm_map_interface(
3460 epm_pipe->binding_handle,
3461 NCALRPC,
3462 iface,
3463 mem_ctx,
3464 psocket_name);
3465 if (!NT_STATUS_IS_OK(status)) {
3466 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3467 nt_errstr(status));
3470 done:
3471 TALLOC_FREE(frame);
3472 return status;
3475 /********************************************************************
3476 Create a rpc pipe client struct, connecting to a unix domain socket
3477 ********************************************************************/
3478 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
3479 const struct ndr_interface_table *table,
3480 struct rpc_pipe_client **presult)
3482 TALLOC_CTX *frame = talloc_stackframe();
3483 char *myname = NULL;
3484 char *socket_name = NULL;
3485 struct samba_sockaddr saddr = {
3486 .sa_socklen = sizeof(struct sockaddr_un),
3487 .u = {
3488 .un = {
3489 .sun_family = AF_UNIX,
3493 struct rpc_client_association *assoc = NULL;
3494 struct rpc_client_connection *conn = NULL;
3495 struct rpc_pipe_client *result = NULL;
3496 int pathlen;
3497 NTSTATUS status;
3498 int fd = -1;
3500 myname = get_myname(frame);
3501 if (myname == NULL) {
3502 TALLOC_FREE(frame);
3503 return NT_STATUS_NO_MEMORY;
3506 status = rpc_pipe_get_ncalrpc_name(&table->syntax_id,
3507 frame,
3508 &socket_name);
3509 if (!NT_STATUS_IS_OK(status)) {
3510 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
3511 nt_errstr(status));
3512 TALLOC_FREE(frame);
3513 return status;
3516 pathlen = snprintf(
3517 saddr.u.un.sun_path,
3518 sizeof(saddr.u.un.sun_path),
3519 "%s/%s",
3520 lp_ncalrpc_dir(),
3521 socket_name);
3522 if ((pathlen < 0) || ((size_t)pathlen >= sizeof(saddr.u.un.sun_path))) {
3523 DBG_DEBUG("socket_path for %s too long\n", socket_name);
3524 TALLOC_FREE(frame);
3525 return NT_STATUS_NAME_TOO_LONG;
3527 TALLOC_FREE(socket_name);
3529 status = rpc_client_association_create(mem_ctx,
3530 0, /* no client_features */
3531 0, /* flags */
3532 myname,
3533 NCALRPC,
3534 &saddr,
3535 socket_name,
3536 &assoc);
3537 if (!NT_STATUS_IS_OK(status)) {
3538 TALLOC_FREE(frame);
3539 return status;
3541 talloc_steal(frame, assoc);
3543 status = rpc_client_connection_create(mem_ctx,
3544 assoc,
3545 DCERPC_FRAG_MAX_SIZE,
3546 &conn);
3547 if (!NT_STATUS_IS_OK(status)) {
3548 TALLOC_FREE(frame);
3549 return status;
3551 talloc_steal(frame, conn);
3553 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3554 if (fd == -1) {
3555 status = map_nt_error_from_unix(errno);
3556 TALLOC_FREE(frame);
3557 return status;
3560 if (connect(fd, &saddr.u.sa, saddr.sa_socklen) == -1) {
3561 status = map_nt_error_from_unix(errno);
3562 close(fd);
3563 DBG_WARNING("connect(%s) failed: %s - %s\n",
3564 saddr.u.un.sun_path,
3565 strerror(errno), nt_errstr(status));
3566 TALLOC_FREE(frame);
3567 return status;
3570 status = rpc_transport_sock_init(conn, fd, &conn->transport);
3571 if (!NT_STATUS_IS_OK(status)) {
3572 close(fd);
3573 TALLOC_FREE(frame);
3574 return status;
3576 fd = -1;
3578 conn->transport->transport = NCALRPC;
3580 status = rpc_pipe_wrap_create(table,
3581 NULL,
3582 &assoc,
3583 &conn,
3584 mem_ctx,
3585 &result);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 TALLOC_FREE(frame);
3588 return status;
3591 *presult = result;
3592 TALLOC_FREE(frame);
3593 return NT_STATUS_OK;
3596 NTSTATUS rpc_pipe_open_local_np(
3597 TALLOC_CTX *mem_ctx,
3598 const struct ndr_interface_table *table,
3599 const char *remote_client_name,
3600 const struct tsocket_address *remote_client_addr,
3601 const char *local_server_name,
3602 const struct tsocket_address *local_server_addr,
3603 const struct auth_session_info *session_info,
3604 struct rpc_pipe_client **presult)
3606 TALLOC_CTX *frame = talloc_stackframe();
3607 struct rpc_client_association *assoc = NULL;
3608 struct rpc_client_connection *conn = NULL;
3609 struct rpc_pipe_client *result = NULL;
3610 struct pipe_auth_data *auth = NULL;
3611 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3612 const char *pipe_name = NULL;
3613 struct tstream_context *npa_stream = NULL;
3614 NTSTATUS status = NT_STATUS_NO_MEMORY;
3615 int ret;
3617 pipe_name = dcerpc_default_transport_endpoint(frame,
3618 NCACN_NP,
3619 table);
3620 if (pipe_name == NULL) {
3621 DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
3622 TALLOC_FREE(frame);
3623 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3626 if (local_server_name == NULL) {
3627 local_server_name = get_myname(result);
3630 if (local_server_addr != NULL) {
3631 saddr.sa_socklen = tsocket_address_bsd_sockaddr(local_server_addr,
3632 &saddr.u.sa,
3633 sizeof(saddr.u.ss));
3634 if (saddr.sa_socklen == -1) {
3635 status = map_nt_error_from_unix(errno);
3636 TALLOC_FREE(frame);
3637 return status;
3641 status = rpc_client_association_create(mem_ctx,
3642 0, /* no client_features */
3643 0, /* flags */
3644 local_server_name,
3645 NCACN_NP,
3646 &saddr,
3647 pipe_name,
3648 &assoc);
3649 if (!NT_STATUS_IS_OK(status)) {
3650 TALLOC_FREE(frame);
3651 return status;
3653 talloc_steal(frame, assoc);
3655 status = rpc_client_connection_create(mem_ctx,
3656 assoc,
3657 DCERPC_FRAG_MAX_SIZE,
3658 &conn);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 TALLOC_FREE(frame);
3661 return status;
3663 talloc_steal(frame, conn);
3665 ret = local_np_connect(
3666 pipe_name,
3667 NCALRPC,
3668 remote_client_name,
3669 remote_client_addr,
3670 local_server_name,
3671 local_server_addr,
3672 session_info,
3673 true,
3674 conn,
3675 &npa_stream);
3676 if (ret != 0) {
3677 DBG_DEBUG("local_np_connect for %s and "
3678 "user %s\\%s failed: %s\n",
3679 pipe_name,
3680 session_info->info->domain_name,
3681 session_info->info->account_name,
3682 strerror(ret));
3683 status = map_nt_error_from_unix(ret);
3684 TALLOC_FREE(frame);
3685 return status;
3688 status = rpc_transport_tstream_init(conn,
3689 &npa_stream,
3690 &conn->transport);
3691 if (!NT_STATUS_IS_OK(status)) {
3692 DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
3693 nt_errstr(status));
3694 TALLOC_FREE(frame);
3695 return status;
3697 conn->transport->transport = NCACN_NP;
3699 status = rpc_pipe_wrap_create(table,
3700 NULL,
3701 &assoc,
3702 &conn,
3703 mem_ctx,
3704 &result);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 TALLOC_FREE(frame);
3707 return status;
3709 talloc_steal(frame, result);
3711 status = rpccli_anon_bind_data(result, &auth);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3714 nt_errstr(status));
3715 TALLOC_FREE(frame);
3716 return status;
3719 status = rpc_pipe_bind(result, auth);
3720 if (!NT_STATUS_IS_OK(status)) {
3721 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3722 TALLOC_FREE(frame);
3723 return status;
3726 *presult = talloc_move(mem_ctx, &result);
3727 TALLOC_FREE(frame);
3728 return NT_STATUS_OK;
3731 struct rpc_client_connection_np_state {
3732 struct cli_state *cli;
3733 const char *pipe_name;
3734 struct rpc_client_connection *conn;
3737 static void rpc_client_connection_np_done(struct tevent_req *subreq);
3739 static struct tevent_req *rpc_client_connection_np_send(
3740 TALLOC_CTX *mem_ctx,
3741 struct tevent_context *ev,
3742 struct cli_state *cli,
3743 const struct rpc_client_association *assoc)
3745 struct tevent_req *req = NULL, *subreq = NULL;
3746 struct rpc_client_connection_np_state *state = NULL;
3747 enum dcerpc_transport_t transport;
3748 const char *endpoint = NULL;
3749 const struct sockaddr_storage *local_sockaddr = NULL;
3750 struct smbXcli_session *session = NULL;
3751 NTSTATUS status;
3753 req = tevent_req_create(mem_ctx, &state,
3754 struct rpc_client_connection_np_state);
3755 if (req == NULL) {
3756 return NULL;
3759 transport = dcerpc_binding_get_transport(assoc->binding);
3760 if (transport != NCACN_NP) {
3761 tevent_req_nterror(req, NT_STATUS_RPC_WRONG_KIND_OF_BINDING);
3762 return tevent_req_post(req, ev);
3765 endpoint = dcerpc_binding_get_string_option(assoc->binding,
3766 "endpoint");
3767 if (endpoint == NULL) {
3768 tevent_req_nterror(req, NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT);
3769 return tevent_req_post(req, ev);
3772 status = rpc_client_connection_create(state,
3773 assoc,
3774 TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE,
3775 &state->conn);
3776 if (tevent_req_nterror(req, status)) {
3777 return tevent_req_post(req, ev);
3780 local_sockaddr = smbXcli_conn_local_sockaddr(cli->conn);
3781 state->conn->localaddr.u.ss = *local_sockaddr;
3783 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3784 session = cli->smb2.session;
3785 } else {
3786 session = cli->smb1.session;
3789 status = smbXcli_session_application_key(session, state->conn,
3790 &state->conn->transport_session_key);
3791 if (!NT_STATUS_IS_OK(status)) {
3792 state->conn->transport_session_key = data_blob_null;
3795 subreq = rpc_transport_np_init_send(state, ev, cli, endpoint);
3796 if (tevent_req_nomem(subreq, req)) {
3797 return tevent_req_post(req, ev);
3799 tevent_req_set_callback(subreq, rpc_client_connection_np_done, req);
3800 return req;
3803 static void rpc_client_connection_np_done(struct tevent_req *subreq)
3805 struct tevent_req *req = tevent_req_callback_data(
3806 subreq, struct tevent_req);
3807 struct rpc_client_connection_np_state *state = tevent_req_data(
3808 req, struct rpc_client_connection_np_state);
3809 NTSTATUS status;
3811 status = rpc_transport_np_init_recv(subreq,
3812 state->conn,
3813 &state->conn->transport);
3814 TALLOC_FREE(subreq);
3815 if (tevent_req_nterror(req, status)) {
3816 return;
3819 state->conn->transport->transport = NCACN_NP;
3821 tevent_req_done(req);
3824 static NTSTATUS rpc_client_connection_np_recv(
3825 struct tevent_req *req,
3826 TALLOC_CTX *mem_ctx,
3827 struct rpc_client_connection **pconn)
3829 struct rpc_client_connection_np_state *state = tevent_req_data(
3830 req, struct rpc_client_connection_np_state);
3831 NTSTATUS status;
3833 if (tevent_req_is_nterror(req, &status)) {
3834 tevent_req_received(req);
3835 return status;
3837 *pconn = talloc_move(mem_ctx, &state->conn);
3838 tevent_req_received(req);
3839 return NT_STATUS_OK;
3842 static NTSTATUS rpc_client_connection_np(struct cli_state *cli,
3843 const struct rpc_client_association *assoc,
3844 struct rpc_client_connection **pconn)
3846 struct tevent_context *ev = NULL;
3847 struct tevent_req *req = NULL;
3848 NTSTATUS status = NT_STATUS_NO_MEMORY;
3850 ev = samba_tevent_context_init(cli);
3851 if (ev == NULL) {
3852 goto fail;
3854 req = rpc_client_connection_np_send(ev, ev, cli, assoc);
3855 if (req == NULL) {
3856 goto fail;
3858 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3859 goto fail;
3861 status = rpc_client_connection_np_recv(req, NULL, pconn);
3862 fail:
3863 TALLOC_FREE(req);
3864 TALLOC_FREE(ev);
3865 return status;
3868 struct rpc_pipe_open_np_state {
3869 struct cli_state *cli;
3870 const struct ndr_interface_table *table;
3871 struct rpc_client_association *assoc;
3872 struct rpc_client_connection *conn;
3873 struct rpc_pipe_client *result;
3876 static void rpc_pipe_open_np_done(struct tevent_req *subreq);
3878 struct tevent_req *rpc_pipe_open_np_send(
3879 TALLOC_CTX *mem_ctx,
3880 struct tevent_context *ev,
3881 struct cli_state *cli,
3882 const struct ndr_interface_table *table)
3884 struct tevent_req *req = NULL, *subreq = NULL;
3885 struct rpc_pipe_open_np_state *state = NULL;
3886 const char *remote_name = NULL;
3887 const struct sockaddr_storage *remote_sockaddr = NULL;
3888 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3889 const char *pipe_name = NULL;
3890 NTSTATUS status;
3892 req = tevent_req_create(
3893 mem_ctx, &state, struct rpc_pipe_open_np_state);
3894 if (req == NULL) {
3895 return NULL;
3897 state->cli = cli;
3898 state->table = table;
3900 remote_name = smbXcli_conn_remote_name(cli->conn);
3901 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
3902 saddr.u.ss = *remote_sockaddr;
3904 pipe_name = dcerpc_default_transport_endpoint(state,
3905 NCACN_NP,
3906 table);
3907 if (tevent_req_nomem(pipe_name, req)) {
3908 return tevent_req_post(req, ev);
3911 status = rpc_client_association_create(state,
3912 default_bt_features,
3913 DCERPC_PROPOSE_HEADER_SIGNING,
3914 remote_name,
3915 NCACN_NP,
3916 &saddr,
3917 pipe_name,
3918 &state->assoc);
3919 if (tevent_req_nterror(req, status)) {
3920 return tevent_req_post(req, ev);
3923 subreq = rpc_client_connection_np_send(state, ev, cli, state->assoc);
3924 if (tevent_req_nomem(subreq, req)) {
3925 return tevent_req_post(req, ev);
3927 tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
3928 return req;
3931 static void rpc_pipe_open_np_done(struct tevent_req *subreq)
3933 struct tevent_req *req = tevent_req_callback_data(
3934 subreq, struct tevent_req);
3935 struct rpc_pipe_open_np_state *state = tevent_req_data(
3936 req, struct rpc_pipe_open_np_state);
3937 NTSTATUS status;
3939 status = rpc_client_connection_np_recv(subreq,
3940 state,
3941 &state->conn);
3942 TALLOC_FREE(subreq);
3943 if (tevent_req_nterror(req, status)) {
3944 return;
3947 status = rpc_pipe_wrap_create(state->table,
3948 state->cli,
3949 &state->assoc,
3950 &state->conn,
3951 state,
3952 &state->result);
3953 if (tevent_req_nterror(req, status)) {
3954 return;
3957 tevent_req_done(req);
3960 NTSTATUS rpc_pipe_open_np_recv(
3961 struct tevent_req *req,
3962 TALLOC_CTX *mem_ctx,
3963 struct rpc_pipe_client **_result)
3965 struct rpc_pipe_open_np_state *state = tevent_req_data(
3966 req, struct rpc_pipe_open_np_state);
3967 NTSTATUS status;
3969 if (tevent_req_is_nterror(req, &status)) {
3970 tevent_req_received(req);
3971 return status;
3973 *_result = talloc_move(mem_ctx, &state->result);
3974 tevent_req_received(req);
3975 return NT_STATUS_OK;
3978 /****************************************************************************
3979 Open a pipe to a remote server.
3980 ****************************************************************************/
3982 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3983 enum dcerpc_transport_t transport,
3984 const struct ndr_interface_table *table,
3985 const char *remote_name,
3986 const struct sockaddr_storage *remote_sockaddr,
3987 struct rpc_pipe_client **presult)
3989 TALLOC_CTX *frame = talloc_stackframe();
3990 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3991 struct rpc_client_association *assoc = NULL;
3992 struct rpc_client_connection *conn = NULL;
3993 struct rpc_pipe_client *result = NULL;
3994 char _tcp_endpoint[6] = { 0, };
3995 const char *endpoint = NULL;
3996 NTSTATUS status;
3998 if (cli != NULL && remote_name == NULL) {
3999 remote_name = smbXcli_conn_remote_name(cli->conn);
4001 if (cli != NULL && remote_sockaddr == NULL) {
4002 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
4005 if (remote_sockaddr != NULL) {
4006 saddr.u.ss = *remote_sockaddr;
4007 } else {
4008 bool ok;
4010 ok = resolve_name(remote_name,
4011 &saddr.u.ss,
4012 NBT_NAME_SERVER,
4013 false);
4014 if (!ok) {
4015 TALLOC_FREE(frame);
4016 return NT_STATUS_NOT_FOUND;
4020 endpoint = dcerpc_default_transport_endpoint(frame,
4021 transport,
4022 table);
4023 if (endpoint == NULL) {
4024 uint16_t port = 0;
4026 if (transport != NCACN_IP_TCP) {
4027 TALLOC_FREE(frame);
4028 return NT_STATUS_RPC_NO_ENDPOINT_FOUND;
4031 status = rpc_pipe_get_tcp_port(remote_name,
4032 &saddr,
4033 table,
4034 &port);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 TALLOC_FREE(frame);
4037 return status;
4040 snprintf(_tcp_endpoint, sizeof(_tcp_endpoint), "%u", port);
4041 endpoint = _tcp_endpoint;
4044 status = rpc_client_association_create(NULL,
4045 default_bt_features,
4046 DCERPC_PROPOSE_HEADER_SIGNING,
4047 remote_name,
4048 transport,
4049 &saddr,
4050 endpoint,
4051 &assoc);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 TALLOC_FREE(frame);
4054 return status;
4056 talloc_steal(frame, assoc);
4058 switch (transport) {
4059 case NCACN_IP_TCP:
4060 status = rpc_pipe_open_tcp_port(NULL,
4061 assoc,
4062 &conn);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 TALLOC_FREE(frame);
4065 return status;
4067 talloc_steal(frame, conn);
4068 break;
4069 case NCACN_NP:
4070 status = rpc_client_connection_np(cli,
4071 assoc,
4072 &conn);
4073 if (!NT_STATUS_IS_OK(status)) {
4074 TALLOC_FREE(frame);
4075 return status;
4077 talloc_steal(frame, conn);
4078 break;
4079 default:
4080 TALLOC_FREE(frame);
4081 return NT_STATUS_NOT_IMPLEMENTED;
4083 status = rpc_pipe_wrap_create(table,
4084 cli,
4085 &assoc,
4086 &conn,
4087 NULL,
4088 &result);
4089 if (!NT_STATUS_IS_OK(status)) {
4090 TALLOC_FREE(frame);
4091 return status;
4094 *presult = result;
4095 TALLOC_FREE(frame);
4096 return NT_STATUS_OK;
4099 static NTSTATUS cli_rpc_pipe_client_reconnect(struct rpc_pipe_client *p)
4101 enum dcerpc_transport_t transport =
4102 dcerpc_binding_get_transport(p->assoc->binding);
4103 NTSTATUS status;
4105 switch (transport) {
4106 case NCACN_IP_TCP:
4107 status = rpc_pipe_open_tcp_port(p,
4108 p->assoc,
4109 &p->conn);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 return status;
4113 break;
4114 case NCACN_NP:
4115 status = rpc_client_connection_np(p->np_cli,
4116 p->assoc,
4117 &p->conn);
4118 if (!NT_STATUS_IS_OK(status)) {
4119 return status;
4121 talloc_steal(p, p->conn);
4122 break;
4123 default:
4124 return NT_STATUS_NOT_IMPLEMENTED;
4127 return NT_STATUS_OK;
4130 NTSTATUS cli_rpc_pipe_client_prepare_alter(struct rpc_pipe_client *p,
4131 bool new_auth_context,
4132 const struct ndr_interface_table *table,
4133 bool new_pres_context)
4135 uint32_t f = p->assoc->features.negotiated;
4136 NTSTATUS status;
4138 if (!new_auth_context && !new_pres_context) {
4139 return NT_STATUS_INVALID_PARAMETER_MIX;
4142 TALLOC_FREE(p->binding_handle);
4144 if (new_auth_context) {
4145 p->auth = NULL;
4148 if (new_auth_context &&
4149 !(f & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING))
4152 * new auth context without
4153 * security context multiplexing.
4155 * We need to create a new transport
4156 * connection is the same association
4157 * group
4159 * We need to keep the old connection alive
4160 * in order to connect to the existing association
4161 * group..., so no TALLOC_FREE(p->conn)
4163 p->conn = NULL;
4164 status = cli_rpc_pipe_client_reconnect(p);
4165 if (!NT_STATUS_IS_OK(status)) {
4166 return status;
4170 if (new_pres_context) {
4171 /* rpc_pipe_bind_send should allocate an id... */
4172 p->pres_context_id = UINT16_MAX;
4173 p->table = table;
4174 p->transfer_syntax = ndr_transfer_syntax_ndr;
4177 return NT_STATUS_OK;
4180 /****************************************************************************
4181 Open a named pipe to an SMB server and bind anonymously.
4182 ****************************************************************************/
4184 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
4185 enum dcerpc_transport_t transport,
4186 const struct ndr_interface_table *table,
4187 const char *remote_name,
4188 const struct sockaddr_storage *remote_sockaddr,
4189 struct rpc_pipe_client **presult)
4191 struct rpc_pipe_client *result;
4192 struct pipe_auth_data *auth;
4193 NTSTATUS status;
4195 status = cli_rpc_pipe_open(cli,
4196 transport,
4197 table,
4198 remote_name,
4199 remote_sockaddr,
4200 &result);
4201 if (!NT_STATUS_IS_OK(status)) {
4202 return status;
4205 status = rpccli_anon_bind_data(result, &auth);
4206 if (!NT_STATUS_IS_OK(status)) {
4207 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
4208 nt_errstr(status)));
4209 TALLOC_FREE(result);
4210 return status;
4213 status = rpc_pipe_bind(result, auth);
4214 if (!NT_STATUS_IS_OK(status)) {
4215 int lvl = 0;
4216 if (ndr_syntax_id_equal(&table->syntax_id,
4217 &ndr_table_dssetup.syntax_id)) {
4218 /* non AD domains just don't have this pipe, avoid
4219 * level 0 statement in that case - gd */
4220 lvl = 3;
4222 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
4223 "%s failed with error %s\n",
4224 table->name,
4225 nt_errstr(status) ));
4226 TALLOC_FREE(result);
4227 return status;
4230 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
4231 "%s and bound anonymously.\n",
4232 table->name,
4233 result->desthost));
4235 *presult = result;
4236 return NT_STATUS_OK;
4239 /****************************************************************************
4240 ****************************************************************************/
4242 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
4243 const struct ndr_interface_table *table,
4244 struct rpc_pipe_client **presult)
4246 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
4247 const struct sockaddr_storage *remote_sockaddr =
4248 smbXcli_conn_remote_sockaddr(cli->conn);
4250 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
4251 table,
4252 remote_name,
4253 remote_sockaddr,
4254 presult);
4257 /****************************************************************************
4258 Open a named pipe to an SMB server and bind using the mech specified
4260 This routine references the creds pointer that is passed in
4261 ****************************************************************************/
4263 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
4264 const struct ndr_interface_table *table,
4265 enum dcerpc_transport_t transport,
4266 enum dcerpc_AuthType auth_type,
4267 enum dcerpc_AuthLevel auth_level,
4268 const char *target_service,
4269 const char *target_hostname,
4270 const struct sockaddr_storage *remote_sockaddr,
4271 struct cli_credentials *creds,
4272 struct rpc_pipe_client **presult)
4274 struct rpc_pipe_client *result;
4275 struct pipe_auth_data *auth = NULL;
4276 NTSTATUS status;
4278 if (target_service == NULL) {
4279 target_service = table->authservices->names[0];
4282 status = cli_rpc_pipe_open(cli,
4283 transport,
4284 table,
4285 target_hostname,
4286 remote_sockaddr,
4287 &result);
4288 if (!NT_STATUS_IS_OK(status)) {
4289 return status;
4292 status = rpccli_generic_bind_data_from_creds(result,
4293 auth_type,
4294 auth_level,
4295 target_hostname,
4296 target_service,
4297 creds,
4298 &auth);
4299 if (!NT_STATUS_IS_OK(status)) {
4300 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
4301 nt_errstr(status));
4302 goto err;
4305 status = rpc_pipe_bind(result, auth);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
4308 nt_errstr(status));
4309 goto err;
4312 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
4313 table->name,
4314 result->desthost,
4315 cli_credentials_get_unparsed_name(creds, talloc_tos()));
4317 *presult = result;
4318 return NT_STATUS_OK;
4320 err:
4322 TALLOC_FREE(result);
4323 return status;
4326 NTSTATUS cli_rpc_pipe_client_auth_schannel(
4327 struct rpc_pipe_client *rpccli,
4328 const struct ndr_interface_table *table,
4329 struct netlogon_creds_cli_context *netlogon_creds)
4331 TALLOC_CTX *frame = talloc_stackframe();
4332 struct pipe_auth_data *rpcauth = NULL;
4333 const char *target_service = table->authservices->names[0];
4334 struct cli_credentials *cli_creds = NULL;
4335 enum dcerpc_AuthLevel auth_level;
4336 NTSTATUS status;
4338 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
4340 status = netlogon_creds_bind_cli_credentials(netlogon_creds,
4341 frame,
4342 &cli_creds);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
4345 nt_errstr(status));
4346 TALLOC_FREE(frame);
4347 return status;
4350 status = rpccli_generic_bind_data_from_creds(rpccli,
4351 DCERPC_AUTH_TYPE_SCHANNEL,
4352 auth_level,
4353 rpccli->desthost,
4354 target_service,
4355 cli_creds,
4356 &rpcauth);
4357 if (!NT_STATUS_IS_OK(status)) {
4358 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
4359 nt_errstr(status)));
4360 TALLOC_FREE(frame);
4361 return status;
4364 status = rpc_pipe_bind(rpccli, rpcauth);
4365 if (!NT_STATUS_IS_OK(status)) {
4366 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
4367 nt_errstr(status));
4368 TALLOC_FREE(frame);
4369 return status;
4372 TALLOC_FREE(frame);
4373 return NT_STATUS_OK;
4376 NTSTATUS cli_rpc_pipe_open_bind_schannel(
4377 struct cli_state *cli,
4378 const struct ndr_interface_table *table,
4379 enum dcerpc_transport_t transport,
4380 struct netlogon_creds_cli_context *netlogon_creds,
4381 const char *remote_name,
4382 const struct sockaddr_storage *remote_sockaddr,
4383 struct rpc_pipe_client **_rpccli)
4385 struct rpc_pipe_client *rpccli = NULL;
4386 NTSTATUS status;
4388 status = cli_rpc_pipe_open(cli,
4389 transport,
4390 table,
4391 remote_name,
4392 remote_sockaddr,
4393 &rpccli);
4394 if (!NT_STATUS_IS_OK(status)) {
4395 return status;
4398 status = cli_rpc_pipe_client_auth_schannel(rpccli,
4399 table,
4400 netlogon_creds);
4401 if (!NT_STATUS_IS_OK(status)) {
4402 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
4403 nt_errstr(status));
4404 TALLOC_FREE(rpccli);
4405 return status;
4408 *_rpccli = rpccli;
4410 return NT_STATUS_OK;
4413 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
4414 const struct ndr_interface_table *table,
4415 enum dcerpc_transport_t transport,
4416 struct netlogon_creds_cli_context *netlogon_creds,
4417 const char *remote_name,
4418 const struct sockaddr_storage *remote_sockaddr,
4419 struct rpc_pipe_client **_rpccli)
4421 TALLOC_CTX *frame = talloc_stackframe();
4422 struct rpc_pipe_client *rpccli;
4423 struct netlogon_creds_cli_lck *lck;
4424 NTSTATUS status;
4426 status = netlogon_creds_cli_lck(
4427 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
4428 frame, &lck);
4429 if (!NT_STATUS_IS_OK(status)) {
4430 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
4431 nt_errstr(status));
4432 TALLOC_FREE(frame);
4433 return status;
4436 status = cli_rpc_pipe_open_bind_schannel(cli,
4437 table,
4438 transport,
4439 netlogon_creds,
4440 remote_name,
4441 remote_sockaddr,
4442 &rpccli);
4443 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
4444 netlogon_creds_cli_delete_lck(netlogon_creds);
4446 if (!NT_STATUS_IS_OK(status)) {
4447 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
4448 nt_errstr(status));
4449 TALLOC_FREE(frame);
4450 return status;
4453 if (ndr_syntax_id_equal(&table->syntax_id,
4454 &ndr_table_netlogon.syntax_id)) {
4455 status = netlogon_creds_cli_check(netlogon_creds,
4456 rpccli->binding_handle,
4457 NULL);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
4460 nt_errstr(status)));
4461 TALLOC_FREE(frame);
4462 return status;
4466 DBG_DEBUG("opened pipe %s to machine %s with key %s "
4467 "and bound using schannel.\n",
4468 table->name, rpccli->desthost,
4469 netlogon_creds_cli_debug_string(netlogon_creds, lck));
4471 TALLOC_FREE(frame);
4473 *_rpccli = rpccli;
4474 return NT_STATUS_OK;