ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source3 / rpc_client / cli_pipe.c
blobd512dde386f6e11f41828a5eafef9a4988767734
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 NTSTATUS status;
85 assoc = talloc_zero(mem_ctx, struct rpc_client_association);
86 if (assoc == NULL) {
87 return NT_STATUS_NO_MEMORY;
89 assoc->features.client = client_features;
90 if (client_features == 0) {
92 * Without requested features there
93 * is no point in trying to negotiate
94 * something, so we are done...
96 assoc->features.negotiation_done = true;
99 status = dcerpc_parse_binding(assoc, "", &bd);
100 if (!NT_STATUS_IS_OK(status)) {
101 TALLOC_FREE(assoc);
102 return status;
104 status = dcerpc_binding_set_transport(bd, transport);
105 if (!NT_STATUS_IS_OK(status)) {
106 TALLOC_FREE(assoc);
107 return status;
109 status = dcerpc_binding_set_string_option(bd,
110 "host",
111 target_hostname);
112 if (!NT_STATUS_IS_OK(status)) {
113 TALLOC_FREE(assoc);
114 return status;
116 status = dcerpc_binding_set_string_option(bd,
117 "target_hostname",
118 target_hostname);
119 if (!NT_STATUS_IS_OK(status)) {
120 TALLOC_FREE(assoc);
121 return status;
123 status = dcerpc_binding_set_string_option(bd,
124 "endpoint",
125 endpoint);
126 if (!NT_STATUS_IS_OK(status)) {
127 TALLOC_FREE(assoc);
128 return status;
130 status = dcerpc_binding_set_flags(bd, flags, 0);
131 if (!NT_STATUS_IS_OK(status)) {
132 TALLOC_FREE(assoc);
133 return status;
136 assoc->binding = bd;
137 assoc->addr = *addr;
139 *passoc = assoc;
140 return NT_STATUS_OK;
143 struct rpc_client_connection {
144 DATA_BLOB transport_session_key;
145 struct rpc_cli_transport *transport;
147 struct {
148 uint16_t max_xmit_frag;
149 uint16_t max_recv_frag;
150 bool client_hdr_signing;
151 bool hdr_signing;
152 bool bind_done;
153 } features;
155 uint32_t next_auth_context_id;
156 uint16_t next_pres_context_id;
159 static NTSTATUS rpc_client_connection_create(TALLOC_CTX *mem_ctx,
160 const struct rpc_client_association *assoc,
161 uint16_t max_frag,
162 struct rpc_client_connection **pconn)
164 struct rpc_client_connection *conn = NULL;
165 uint32_t flags = dcerpc_binding_get_flags(assoc->binding);
166 bool client_hdr_signing = (flags & DCERPC_PROPOSE_HEADER_SIGNING);
168 conn = talloc_zero(mem_ctx, struct rpc_client_connection);
169 if (conn == NULL) {
170 return NT_STATUS_NO_MEMORY;
172 conn->features.max_xmit_frag = max_frag;
173 conn->features.max_recv_frag = max_frag;
174 conn->features.client_hdr_signing = client_hdr_signing;
176 *pconn = conn;
177 return NT_STATUS_OK;
180 static int rpc_pipe_client_wrap_destructor(struct rpc_pipe_client *p)
182 if (p->np_cli != NULL) {
183 DLIST_REMOVE(p->np_cli->pipe_list, p);
184 p->np_cli = NULL;
187 return 0;
190 static NTSTATUS rpc_pipe_wrap_create(
191 const struct ndr_interface_table *table,
192 struct cli_state *np_cli,
193 struct rpc_client_association **passoc,
194 struct rpc_client_connection **pconn,
195 TALLOC_CTX *mem_ctx,
196 struct rpc_pipe_client **presult)
198 struct rpc_pipe_client *result = NULL;
199 const char *hostname = NULL;
201 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
202 if (result == NULL) {
203 return NT_STATUS_NO_MEMORY;
205 talloc_set_destructor(result, rpc_pipe_client_wrap_destructor);
207 result->assoc = talloc_move(result, passoc);
208 result->conn = talloc_move(result, pconn);
210 /* rpc_pipe_bind_send should allocate an id... */
211 result->pres_context_id = UINT16_MAX;
212 result->table = table;
213 result->transfer_syntax = ndr_transfer_syntax_ndr;
215 hostname = dcerpc_binding_get_string_option(result->assoc->binding,
216 "target_hostname");
217 result->desthost = talloc_strdup(result, hostname);
218 if (result->desthost == NULL) {
219 TALLOC_FREE(result);
220 return NT_STATUS_NO_MEMORY;
223 result->srv_name_slash = talloc_asprintf_strupper_m(
224 result, "\\\\%s", result->desthost);
225 if (result->srv_name_slash == NULL) {
226 TALLOC_FREE(result);
227 return NT_STATUS_NO_MEMORY;
230 if (np_cli != NULL) {
231 result->np_cli = np_cli;
232 DLIST_ADD_END(np_cli->pipe_list, result);
235 *presult = result;
236 return NT_STATUS_OK;
239 /********************************************************************
240 Pipe description for a DEBUG
241 ********************************************************************/
242 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
243 struct rpc_pipe_client *cli)
245 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
246 if (result == NULL) {
247 return "pipe";
249 return result;
252 /*******************************************************************
253 Use SMBreadX to get rest of one fragment's worth of rpc data.
254 Reads the whole size or give an error message
255 ********************************************************************/
257 struct rpc_read_state {
258 struct tevent_context *ev;
259 struct rpc_cli_transport *transport;
260 uint8_t *data;
261 size_t size;
262 size_t num_read;
265 static void rpc_read_done(struct tevent_req *subreq);
267 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
268 struct tevent_context *ev,
269 struct rpc_cli_transport *transport,
270 uint8_t *data, size_t size)
272 struct tevent_req *req, *subreq;
273 struct rpc_read_state *state;
275 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
276 if (req == NULL) {
277 return NULL;
279 state->ev = ev;
280 state->transport = transport;
281 state->data = data;
282 state->size = size;
283 state->num_read = 0;
285 DBG_INFO("data_to_read: %zu\n", size);
287 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
288 transport->priv);
289 if (subreq == NULL) {
290 goto fail;
292 tevent_req_set_callback(subreq, rpc_read_done, req);
293 return req;
295 fail:
296 TALLOC_FREE(req);
297 return NULL;
300 static void rpc_read_done(struct tevent_req *subreq)
302 struct tevent_req *req = tevent_req_callback_data(
303 subreq, struct tevent_req);
304 struct rpc_read_state *state = tevent_req_data(
305 req, struct rpc_read_state);
306 NTSTATUS status;
307 ssize_t received;
309 status = state->transport->read_recv(subreq, &received);
310 TALLOC_FREE(subreq);
311 if (tevent_req_nterror(req, status)) {
312 return;
315 state->num_read += received;
316 if (state->num_read == state->size) {
317 tevent_req_done(req);
318 return;
321 subreq = state->transport->read_send(state, state->ev,
322 state->data + state->num_read,
323 state->size - state->num_read,
324 state->transport->priv);
325 if (tevent_req_nomem(subreq, req)) {
326 return;
328 tevent_req_set_callback(subreq, rpc_read_done, req);
331 static NTSTATUS rpc_read_recv(struct tevent_req *req)
333 return tevent_req_simple_recv_ntstatus(req);
336 struct rpc_write_state {
337 struct tevent_context *ev;
338 struct rpc_cli_transport *transport;
339 const uint8_t *data;
340 size_t size;
341 size_t num_written;
344 static void rpc_write_done(struct tevent_req *subreq);
346 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
347 struct tevent_context *ev,
348 struct rpc_cli_transport *transport,
349 const uint8_t *data, size_t size)
351 struct tevent_req *req, *subreq;
352 struct rpc_write_state *state;
354 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
355 if (req == NULL) {
356 return NULL;
358 state->ev = ev;
359 state->transport = transport;
360 state->data = data;
361 state->size = size;
362 state->num_written = 0;
364 DBG_INFO("data_to_write: %zu\n", size);
366 subreq = transport->write_send(state, ev, data, size, transport->priv);
367 if (tevent_req_nomem(subreq, req)) {
368 return tevent_req_post(req, ev);
370 tevent_req_set_callback(subreq, rpc_write_done, req);
371 return req;
374 static void rpc_write_done(struct tevent_req *subreq)
376 struct tevent_req *req = tevent_req_callback_data(
377 subreq, struct tevent_req);
378 struct rpc_write_state *state = tevent_req_data(
379 req, struct rpc_write_state);
380 NTSTATUS status;
381 ssize_t written;
383 status = state->transport->write_recv(subreq, &written);
384 TALLOC_FREE(subreq);
385 if (tevent_req_nterror(req, status)) {
386 return;
389 state->num_written += written;
391 if (state->num_written == state->size) {
392 tevent_req_done(req);
393 return;
396 subreq = state->transport->write_send(state, state->ev,
397 state->data + state->num_written,
398 state->size - state->num_written,
399 state->transport->priv);
400 if (tevent_req_nomem(subreq, req)) {
401 return;
403 tevent_req_set_callback(subreq, rpc_write_done, req);
406 static NTSTATUS rpc_write_recv(struct tevent_req *req)
408 return tevent_req_simple_recv_ntstatus(req);
412 /****************************************************************************
413 Try and get a PDU's worth of data from current_pdu. If not, then read more
414 from the wire.
415 ****************************************************************************/
417 struct get_complete_frag_state {
418 struct tevent_context *ev;
419 struct rpc_pipe_client *cli;
420 uint16_t frag_len;
421 DATA_BLOB *pdu;
424 static void get_complete_frag_got_header(struct tevent_req *subreq);
425 static void get_complete_frag_got_rest(struct tevent_req *subreq);
427 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
428 struct tevent_context *ev,
429 struct rpc_pipe_client *cli,
430 DATA_BLOB *pdu)
432 struct tevent_req *req, *subreq;
433 struct get_complete_frag_state *state;
434 size_t received;
436 req = tevent_req_create(mem_ctx, &state,
437 struct get_complete_frag_state);
438 if (req == NULL) {
439 return NULL;
441 state->ev = ev;
442 state->cli = cli;
443 state->frag_len = RPC_HEADER_LEN;
444 state->pdu = pdu;
446 received = pdu->length;
447 if (received < RPC_HEADER_LEN) {
448 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
449 tevent_req_oom(req);
450 return tevent_req_post(req, ev);
452 subreq = rpc_read_send(state, state->ev,
453 state->cli->conn->transport,
454 pdu->data + received,
455 RPC_HEADER_LEN - received);
456 if (tevent_req_nomem(subreq, req)) {
457 return tevent_req_post(req, ev);
459 tevent_req_set_callback(subreq, get_complete_frag_got_header,
460 req);
461 return req;
464 state->frag_len = dcerpc_get_frag_length(pdu);
465 if (state->frag_len < RPC_HEADER_LEN) {
466 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
467 return tevent_req_post(req, ev);
470 if (received >= state->frag_len) {
472 * Got the whole fragment
474 tevent_req_done(req);
475 return tevent_req_post(req, ev);
478 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
479 tevent_req_oom(req);
480 return tevent_req_post(req, ev);
483 subreq = rpc_read_send(
484 state,
485 state->ev,
486 state->cli->conn->transport,
487 pdu->data + received,
488 state->frag_len - received);
489 if (tevent_req_nomem(subreq, req)) {
490 return tevent_req_post(req, ev);
492 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
493 return req;
496 static void get_complete_frag_got_header(struct tevent_req *subreq)
498 struct tevent_req *req = tevent_req_callback_data(
499 subreq, struct tevent_req);
500 struct get_complete_frag_state *state = tevent_req_data(
501 req, struct get_complete_frag_state);
502 NTSTATUS status;
504 status = rpc_read_recv(subreq);
505 TALLOC_FREE(subreq);
506 if (tevent_req_nterror(req, status)) {
507 return;
510 state->frag_len = dcerpc_get_frag_length(state->pdu);
511 if (state->frag_len < RPC_HEADER_LEN) {
512 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
513 return;
516 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
517 tevent_req_oom(req);
518 return;
522 * We're here in this piece of code because we've read exactly
523 * RPC_HEADER_LEN bytes into state->pdu.
526 subreq = rpc_read_send(state, state->ev,
527 state->cli->conn->transport,
528 state->pdu->data + RPC_HEADER_LEN,
529 state->frag_len - RPC_HEADER_LEN);
530 if (tevent_req_nomem(subreq, req)) {
531 return;
533 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
536 static void get_complete_frag_got_rest(struct tevent_req *subreq)
538 NTSTATUS status = rpc_read_recv(subreq);
539 return tevent_req_simple_finish_ntstatus(subreq, status);
542 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
544 return tevent_req_simple_recv_ntstatus(req);
547 /****************************************************************************
548 Do basic authentication checks on an incoming pdu.
549 ****************************************************************************/
551 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
552 struct rpc_pipe_client *cli,
553 struct ncacn_packet *pkt,
554 DATA_BLOB *pdu,
555 uint8_t expected_pkt_type,
556 uint32_t call_id,
557 DATA_BLOB *rdata,
558 DATA_BLOB *reply_pdu)
560 const struct dcerpc_response *r = NULL;
561 DATA_BLOB tmp_stub = { .data = NULL };
562 NTSTATUS ret;
565 * Point the return values at the real data including the RPC
566 * header. Just in case the caller wants it.
568 *rdata = *pdu;
570 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
571 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
573 * TODO: do we still need this hack which was introduced
574 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
576 * I don't even know what AS/U might be...
578 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
579 "fragment first/last ON.\n"));
580 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
583 /* Ensure we have the correct type. */
584 switch (pkt->ptype) {
585 case DCERPC_PKT_BIND_NAK:
586 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
587 rpccli_pipe_txt(talloc_tos(), cli)));
589 ret = dcerpc_verify_ncacn_packet_header(pkt,
590 DCERPC_PKT_BIND_NAK,
591 0, /* max_auth_info */
592 DCERPC_PFC_FLAG_FIRST |
593 DCERPC_PFC_FLAG_LAST,
594 0); /* optional flags */
595 if (!NT_STATUS_IS_OK(ret)) {
596 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
597 "RPC packet type - %u, expected %u: %s\n",
598 rpccli_pipe_txt(talloc_tos(), cli),
599 pkt->ptype, expected_pkt_type,
600 nt_errstr(ret)));
601 NDR_PRINT_DEBUG(ncacn_packet, pkt);
602 return ret;
605 /* Use this for now... */
606 return NT_STATUS_NETWORK_ACCESS_DENIED;
608 case DCERPC_PKT_BIND_ACK:
609 ret = dcerpc_verify_ncacn_packet_header(pkt,
610 expected_pkt_type,
611 pkt->u.bind_ack.auth_info.length,
612 DCERPC_PFC_FLAG_FIRST |
613 DCERPC_PFC_FLAG_LAST,
614 DCERPC_PFC_FLAG_CONC_MPX |
615 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
616 if (!NT_STATUS_IS_OK(ret)) {
617 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
618 "RPC packet type - %u, expected %u: %s\n",
619 rpccli_pipe_txt(talloc_tos(), cli),
620 pkt->ptype, expected_pkt_type,
621 nt_errstr(ret)));
622 NDR_PRINT_DEBUG(ncacn_packet, pkt);
623 return ret;
626 break;
628 case DCERPC_PKT_ALTER_RESP:
629 ret = dcerpc_verify_ncacn_packet_header(pkt,
630 expected_pkt_type,
631 pkt->u.alter_resp.auth_info.length,
632 DCERPC_PFC_FLAG_FIRST |
633 DCERPC_PFC_FLAG_LAST,
634 DCERPC_PFC_FLAG_CONC_MPX |
635 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
636 if (!NT_STATUS_IS_OK(ret)) {
637 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
638 "RPC packet type - %u, expected %u: %s\n",
639 rpccli_pipe_txt(talloc_tos(), cli),
640 pkt->ptype, expected_pkt_type,
641 nt_errstr(ret)));
642 NDR_PRINT_DEBUG(ncacn_packet, pkt);
643 return ret;
646 break;
648 case DCERPC_PKT_RESPONSE:
650 r = &pkt->u.response;
652 ret = dcerpc_verify_ncacn_packet_header(pkt,
653 expected_pkt_type,
654 r->stub_and_verifier.length,
655 0, /* required_flags */
656 DCERPC_PFC_FLAG_FIRST |
657 DCERPC_PFC_FLAG_LAST);
658 if (!NT_STATUS_IS_OK(ret)) {
659 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
660 "RPC packet type - %u, expected %u: %s\n",
661 rpccli_pipe_txt(talloc_tos(), cli),
662 pkt->ptype, expected_pkt_type,
663 nt_errstr(ret)));
664 NDR_PRINT_DEBUG(ncacn_packet, pkt);
665 return ret;
668 tmp_stub.data = r->stub_and_verifier.data;
669 tmp_stub.length = r->stub_and_verifier.length;
671 /* Here's where we deal with incoming sign/seal. */
672 ret = dcerpc_check_auth(cli->auth, pkt,
673 &tmp_stub,
674 DCERPC_RESPONSE_LENGTH,
675 pdu);
676 if (!NT_STATUS_IS_OK(ret)) {
677 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
678 "RPC packet type - %u, expected %u: %s\n",
679 rpccli_pipe_txt(talloc_tos(), cli),
680 pkt->ptype, expected_pkt_type,
681 nt_errstr(ret)));
682 NDR_PRINT_DEBUG(ncacn_packet, pkt);
683 return ret;
686 /* Point the return values at the NDR data. */
687 *rdata = tmp_stub;
689 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
690 (long unsigned int)pdu->length,
691 (long unsigned int)rdata->length));
694 * If this is the first reply, and the allocation hint is
695 * reasonable, try and set up the reply_pdu DATA_BLOB to the
696 * correct size.
699 if ((reply_pdu->length == 0) &&
700 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
701 if (!data_blob_realloc(mem_ctx, reply_pdu,
702 r->alloc_hint)) {
703 DEBUG(0, ("reply alloc hint %d too "
704 "large to allocate\n",
705 (int)r->alloc_hint));
706 return NT_STATUS_NO_MEMORY;
710 break;
712 case DCERPC_PKT_FAULT:
714 ret = dcerpc_verify_ncacn_packet_header(pkt,
715 DCERPC_PKT_FAULT,
716 0, /* max_auth_info */
717 DCERPC_PFC_FLAG_FIRST |
718 DCERPC_PFC_FLAG_LAST,
719 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
720 if (!NT_STATUS_IS_OK(ret)) {
721 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
722 "RPC packet type - %u, expected %u: %s\n",
723 rpccli_pipe_txt(talloc_tos(), cli),
724 pkt->ptype, expected_pkt_type,
725 nt_errstr(ret)));
726 NDR_PRINT_DEBUG(ncacn_packet, pkt);
727 return ret;
730 DEBUG(1, (__location__ ": RPC fault code %s received "
731 "from %s!\n",
732 dcerpc_errstr(talloc_tos(),
733 pkt->u.fault.status),
734 rpccli_pipe_txt(talloc_tos(), cli)));
736 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
738 default:
739 DEBUG(0, (__location__ "Unknown packet type %u received "
740 "from %s!\n",
741 (unsigned int)pkt->ptype,
742 rpccli_pipe_txt(talloc_tos(), cli)));
743 return NT_STATUS_RPC_PROTOCOL_ERROR;
747 if (pkt->call_id != call_id) {
748 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
749 "RPC call_id - %u, not %u\n",
750 rpccli_pipe_txt(talloc_tos(), cli),
751 pkt->call_id, call_id));
752 return NT_STATUS_RPC_PROTOCOL_ERROR;
755 return NT_STATUS_OK;
758 /****************************************************************************
759 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
760 ****************************************************************************/
762 struct cli_api_pipe_state {
763 struct tevent_context *ev;
764 struct rpc_cli_transport *transport;
765 uint8_t *rdata;
766 uint32_t rdata_len;
769 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
770 static void cli_api_pipe_write_done(struct tevent_req *subreq);
771 static void cli_api_pipe_read_done(struct tevent_req *subreq);
773 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
774 struct tevent_context *ev,
775 struct rpc_cli_transport *transport,
776 uint8_t *data, size_t data_len,
777 uint32_t max_rdata_len)
779 struct tevent_req *req, *subreq;
780 struct cli_api_pipe_state *state;
782 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
783 if (req == NULL) {
784 return NULL;
786 state->ev = ev;
787 state->transport = transport;
789 if (max_rdata_len < RPC_HEADER_LEN) {
791 * For a RPC reply we always need at least RPC_HEADER_LEN
792 * bytes. We check this here because we will receive
793 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
795 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
796 return tevent_req_post(req, ev);
799 if (transport->trans_send != NULL) {
800 subreq = transport->trans_send(state, ev, data, data_len,
801 max_rdata_len, transport->priv);
802 if (tevent_req_nomem(subreq, req)) {
803 return tevent_req_post(req, ev);
805 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
806 return req;
810 * If the transport does not provide a "trans" routine, i.e. for
811 * example the ncacn_ip_tcp transport, do the write/read step here.
814 subreq = rpc_write_send(state, ev, transport, data, data_len);
815 if (tevent_req_nomem(subreq, req)) {
816 return tevent_req_post(req, ev);
818 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
819 return req;
822 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
824 struct tevent_req *req = tevent_req_callback_data(
825 subreq, struct tevent_req);
826 struct cli_api_pipe_state *state = tevent_req_data(
827 req, struct cli_api_pipe_state);
828 NTSTATUS status;
830 status = state->transport->trans_recv(subreq, state, &state->rdata,
831 &state->rdata_len);
832 TALLOC_FREE(subreq);
833 if (tevent_req_nterror(req, status)) {
834 return;
836 tevent_req_done(req);
839 static void cli_api_pipe_write_done(struct tevent_req *subreq)
841 struct tevent_req *req = tevent_req_callback_data(
842 subreq, struct tevent_req);
843 struct cli_api_pipe_state *state = tevent_req_data(
844 req, struct cli_api_pipe_state);
845 NTSTATUS status;
847 status = rpc_write_recv(subreq);
848 TALLOC_FREE(subreq);
849 if (tevent_req_nterror(req, status)) {
850 return;
853 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
854 if (tevent_req_nomem(state->rdata, req)) {
855 return;
859 * We don't need to use rpc_read_send here, the upper layer will cope
860 * with a short read, transport->trans_send could also return less
861 * than state->max_rdata_len.
863 subreq = state->transport->read_send(state, state->ev, state->rdata,
864 RPC_HEADER_LEN,
865 state->transport->priv);
866 if (tevent_req_nomem(subreq, req)) {
867 return;
869 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
872 static void cli_api_pipe_read_done(struct tevent_req *subreq)
874 struct tevent_req *req = tevent_req_callback_data(
875 subreq, struct tevent_req);
876 struct cli_api_pipe_state *state = tevent_req_data(
877 req, struct cli_api_pipe_state);
878 NTSTATUS status;
879 ssize_t received;
881 status = state->transport->read_recv(subreq, &received);
882 TALLOC_FREE(subreq);
883 if (tevent_req_nterror(req, status)) {
884 return;
886 state->rdata_len = received;
887 tevent_req_done(req);
890 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
891 uint8_t **prdata, uint32_t *prdata_len)
893 struct cli_api_pipe_state *state = tevent_req_data(
894 req, struct cli_api_pipe_state);
895 NTSTATUS status;
897 if (tevent_req_is_nterror(req, &status)) {
898 return status;
901 *prdata = talloc_move(mem_ctx, &state->rdata);
902 *prdata_len = state->rdata_len;
903 return NT_STATUS_OK;
906 /****************************************************************************
907 Send data on an rpc pipe via trans. The data must be the last
908 pdu fragment of an NDR data stream.
910 Receive response data from an rpc pipe, which may be large...
912 Read the first fragment: unfortunately have to use SMBtrans for the first
913 bit, then SMBreadX for subsequent bits.
915 If first fragment received also wasn't the last fragment, continue
916 getting fragments until we _do_ receive the last fragment.
918 Request/Response PDU's look like the following...
920 |<------------------PDU len----------------------------------------------->|
921 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
923 +------------+-----------------+-------------+---------------+-------------+
924 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
925 +------------+-----------------+-------------+---------------+-------------+
927 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
928 signing & sealing being negotiated.
930 ****************************************************************************/
932 struct rpc_api_pipe_state {
933 struct tevent_context *ev;
934 struct rpc_pipe_client *cli;
935 uint8_t expected_pkt_type;
936 uint32_t call_id;
938 DATA_BLOB incoming_frag;
939 struct ncacn_packet *pkt;
941 /* Incoming reply */
942 DATA_BLOB reply_pdu;
943 size_t reply_pdu_offset;
944 uint8_t endianness;
947 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
948 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
949 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
951 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
952 struct tevent_context *ev,
953 struct rpc_pipe_client *cli,
954 DATA_BLOB *data, /* Outgoing PDU */
955 uint8_t expected_pkt_type,
956 uint32_t call_id)
958 struct tevent_req *req, *subreq;
959 struct rpc_api_pipe_state *state;
960 uint16_t max_recv_frag;
962 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
963 if (req == NULL) {
964 return NULL;
966 state->ev = ev;
967 state->cli = cli;
968 state->expected_pkt_type = expected_pkt_type;
969 state->call_id = call_id;
970 state->endianness = DCERPC_DREP_LE;
973 * Ensure we're not sending too much.
975 if (data->length > cli->conn->features.max_xmit_frag) {
976 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 return tevent_req_post(req, ev);
980 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
982 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
983 subreq = rpc_write_send(state, ev, cli->conn->transport,
984 data->data, data->length);
985 if (tevent_req_nomem(subreq, req)) {
986 return tevent_req_post(req, ev);
988 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
989 return req;
992 /* get the header first, then fetch the rest once we have
993 * the frag_length available */
994 max_recv_frag = RPC_HEADER_LEN;
996 subreq = cli_api_pipe_send(state, ev, cli->conn->transport,
997 data->data, data->length, max_recv_frag);
998 if (tevent_req_nomem(subreq, req)) {
999 return tevent_req_post(req, ev);
1001 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1002 return req;
1005 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
1007 NTSTATUS status = rpc_write_recv(subreq);
1008 return tevent_req_simple_finish_ntstatus(subreq, status);
1011 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1013 struct tevent_req *req = tevent_req_callback_data(
1014 subreq, struct tevent_req);
1015 struct rpc_api_pipe_state *state = tevent_req_data(
1016 req, struct rpc_api_pipe_state);
1017 NTSTATUS status;
1018 uint8_t *rdata = NULL;
1019 uint32_t rdata_len = 0;
1021 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1022 TALLOC_FREE(subreq);
1023 if (tevent_req_nterror(req, status)) {;
1024 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1025 return;
1028 if (rdata == NULL) {
1029 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1030 rpccli_pipe_txt(talloc_tos(), state->cli)));
1031 tevent_req_done(req);
1032 return;
1036 * Move data on state->incoming_frag.
1038 state->incoming_frag.data = talloc_move(state, &rdata);
1039 state->incoming_frag.length = rdata_len;
1040 if (!state->incoming_frag.data) {
1041 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1042 return;
1045 /* Ensure we have enough data for a pdu. */
1046 subreq = get_complete_frag_send(state, state->ev, state->cli,
1047 &state->incoming_frag);
1048 if (tevent_req_nomem(subreq, req)) {
1049 return;
1051 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1054 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct rpc_api_pipe_state *state = tevent_req_data(
1059 req, struct rpc_api_pipe_state);
1060 NTSTATUS status;
1061 DATA_BLOB rdata = { .data = NULL };
1063 status = get_complete_frag_recv(subreq);
1064 TALLOC_FREE(subreq);
1065 if (tevent_req_nterror(req, status)) {
1066 DEBUG(5, ("get_complete_frag failed: %s\n",
1067 nt_errstr(status)));
1068 return;
1071 state->pkt = talloc(state, struct ncacn_packet);
1072 if (!state->pkt) {
1074 * TODO: do a real async disconnect ...
1076 * For now do it sync...
1078 TALLOC_FREE(state->cli->conn);
1079 tevent_req_oom(req);
1080 return;
1083 status = dcerpc_pull_ncacn_packet(state->pkt,
1084 &state->incoming_frag,
1085 state->pkt);
1086 if (tevent_req_nterror(req, status)) {
1088 * TODO: do a real async disconnect ...
1090 * For now do it sync...
1092 TALLOC_FREE(state->cli->conn);
1093 return;
1096 if (DEBUGLEVEL >= 10) {
1097 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
1100 status = cli_pipe_validate_current_pdu(state,
1101 state->cli, state->pkt,
1102 &state->incoming_frag,
1103 state->expected_pkt_type,
1104 state->call_id,
1105 &rdata,
1106 &state->reply_pdu);
1108 DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
1109 state->incoming_frag.length,
1110 state->reply_pdu_offset,
1111 nt_errstr(status));
1113 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
1115 * TODO: do a real async disconnect ...
1117 * For now do it sync...
1119 TALLOC_FREE(state->cli->conn);
1120 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1122 * TODO: do a real async disconnect ...
1124 * For now do it sync...
1126 TALLOC_FREE(state->cli->conn);
1127 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1129 * TODO: do a real async disconnect ...
1131 * For now do it sync...
1133 TALLOC_FREE(state->cli->conn);
1135 if (tevent_req_nterror(req, status)) {
1136 return;
1139 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1140 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1142 * Set the data type correctly for big-endian data on the
1143 * first packet.
1145 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1146 "big-endian.\n",
1147 rpccli_pipe_txt(talloc_tos(), state->cli)));
1148 state->endianness = 0x00; /* BIG ENDIAN */
1151 * Check endianness on subsequent packets.
1153 if (state->endianness != state->pkt->drep[0]) {
1154 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1155 "%s\n",
1156 state->endianness?"little":"big",
1157 state->pkt->drep[0]?"little":"big"));
1159 * TODO: do a real async disconnect ...
1161 * For now do it sync...
1163 TALLOC_FREE(state->cli->conn);
1164 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1165 return;
1168 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1170 * TODO: do a real async disconnect ...
1172 * For now do it sync...
1174 TALLOC_FREE(state->cli->conn);
1175 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1176 return;
1179 /* Now copy the data portion out of the pdu into rbuf. */
1180 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1181 if (!data_blob_realloc(NULL, &state->reply_pdu,
1182 state->reply_pdu_offset + rdata.length)) {
1184 * TODO: do a real async disconnect ...
1186 * For now do it sync...
1188 TALLOC_FREE(state->cli->conn);
1189 tevent_req_oom(req);
1190 return;
1194 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1195 rdata.data, rdata.length);
1196 state->reply_pdu_offset += rdata.length;
1198 /* reset state->incoming_frag, there is no need to free it,
1199 * it will be reallocated to the right size the next time
1200 * it is used */
1201 state->incoming_frag.length = 0;
1203 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1204 /* make sure the pdu length is right now that we
1205 * have all the data available (alloc hint may
1206 * have allocated more than was actually used) */
1207 state->reply_pdu.length = state->reply_pdu_offset;
1208 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1209 rpccli_pipe_txt(talloc_tos(), state->cli),
1210 (unsigned)state->reply_pdu.length));
1211 tevent_req_done(req);
1212 return;
1215 subreq = get_complete_frag_send(state, state->ev, state->cli,
1216 &state->incoming_frag);
1217 if (subreq == NULL) {
1219 * TODO: do a real async disconnect ...
1221 * For now do it sync...
1223 TALLOC_FREE(state->cli->conn);
1225 if (tevent_req_nomem(subreq, req)) {
1226 return;
1228 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1231 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1232 struct ncacn_packet **pkt,
1233 DATA_BLOB *reply_pdu)
1235 struct rpc_api_pipe_state *state = tevent_req_data(
1236 req, struct rpc_api_pipe_state);
1237 NTSTATUS status;
1239 if (tevent_req_is_nterror(req, &status)) {
1240 return status;
1243 /* return data to caller and assign it ownership of memory */
1244 if (reply_pdu) {
1245 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1246 reply_pdu->length = state->reply_pdu.length;
1247 state->reply_pdu.length = 0;
1248 } else {
1249 data_blob_free(&state->reply_pdu);
1252 if (pkt) {
1253 *pkt = talloc_steal(mem_ctx, state->pkt);
1256 return NT_STATUS_OK;
1259 /*******************************************************************
1260 Creates NTLMSSP auth bind.
1261 ********************************************************************/
1263 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1264 TALLOC_CTX *mem_ctx,
1265 DATA_BLOB *auth_token)
1267 struct gensec_security *gensec_security;
1268 DATA_BLOB null_blob = { .data = NULL };
1269 NTSTATUS status;
1271 gensec_security = cli->auth->auth_ctx;
1273 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1274 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1276 if (!NT_STATUS_IS_OK(status) &&
1277 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1279 return status;
1282 return status;
1285 /*******************************************************************
1286 Creates the internals of a DCE/RPC bind request or alter context PDU.
1287 ********************************************************************/
1289 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1290 enum dcerpc_pkt_type ptype,
1291 uint32_t rpc_call_id,
1292 struct rpc_client_association *assoc,
1293 struct rpc_client_connection *conn,
1294 uint16_t pres_context_id,
1295 const struct ndr_syntax_id *abstract,
1296 const struct ndr_syntax_id *transfer,
1297 const DATA_BLOB *auth_info,
1298 DATA_BLOB *blob)
1300 uint16_t auth_len = auth_info->length;
1301 NTSTATUS status;
1302 struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
1303 assoc->features.client);
1304 struct dcerpc_ctx_list ctx_list[2] = {
1305 [0] = {
1306 .context_id = pres_context_id,
1307 .num_transfer_syntaxes = 1,
1308 .abstract_syntax = *abstract,
1309 .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
1311 [1] = {
1313 * For now we assume pres_context_id is 0
1314 * because bind time feature negotiation
1315 * only happens once per association,
1316 * with the first DCERPC Bind.
1318 * With that we use pres_context_id + 1,
1319 * but only consume it from conn->next_pres_context_id
1320 * in check_bind_response().
1322 .context_id = pres_context_id + 1,
1323 .num_transfer_syntaxes = 1,
1324 .abstract_syntax = *abstract,
1325 .transfer_syntaxes = &bind_time_features,
1328 uint32_t assoc_group_id =
1329 dcerpc_binding_get_assoc_group_id(assoc->binding);
1330 union dcerpc_payload u = {
1331 .bind.max_xmit_frag = conn->features.max_xmit_frag,
1332 .bind.max_recv_frag = conn->features.max_recv_frag,
1333 .bind.assoc_group_id = assoc_group_id,
1334 .bind.num_contexts = assoc->features.negotiation_done ? 1 : 2,
1335 .bind.ctx_list = ctx_list,
1336 .bind.auth_info = *auth_info,
1338 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1340 if (conn->features.client_hdr_signing &&
1341 auth_len != 0 &&
1342 !conn->features.hdr_signing)
1345 * The first authenticated bind or alter_context
1346 * negotiates header signing
1348 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1351 if (auth_len) {
1352 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1355 status = dcerpc_push_ncacn_packet(mem_ctx,
1356 ptype, pfc_flags,
1357 auth_len,
1358 rpc_call_id,
1360 blob);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1363 return status;
1366 return NT_STATUS_OK;
1369 /*******************************************************************
1370 Creates a DCE/RPC bind request.
1371 ********************************************************************/
1373 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1374 struct rpc_pipe_client *cli,
1375 struct pipe_auth_data *auth,
1376 uint32_t rpc_call_id,
1377 const struct ndr_syntax_id *abstract,
1378 const struct ndr_syntax_id *transfer,
1379 DATA_BLOB *rpc_out)
1381 enum dcerpc_pkt_type ptype = DCERPC_PKT_BIND;
1382 DATA_BLOB auth_token = { .data = NULL };
1383 DATA_BLOB auth_info = { .data = NULL };
1384 NTSTATUS ret;
1386 if (cli->conn->features.bind_done) {
1387 ptype = DCERPC_PKT_ALTER;
1390 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
1391 ret = create_generic_auth_rpc_bind_req(
1392 cli, mem_ctx, &auth_token);
1394 if (!NT_STATUS_IS_OK(ret) &&
1395 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1396 return ret;
1400 if (auth_token.length != 0) {
1401 ret = dcerpc_push_dcerpc_auth(cli,
1402 auth->auth_type,
1403 auth->auth_level,
1404 0, /* auth_pad_length */
1405 auth->auth_context_id,
1406 &auth_token,
1407 &auth_info);
1408 if (!NT_STATUS_IS_OK(ret)) {
1409 return ret;
1411 data_blob_free(&auth_token);
1414 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1415 ptype,
1416 rpc_call_id,
1417 cli->assoc,
1418 cli->conn,
1419 cli->pres_context_id,
1420 abstract,
1421 transfer,
1422 &auth_info,
1423 rpc_out);
1424 data_blob_free(&auth_info);
1426 return ret;
1429 /*******************************************************************
1430 External interface.
1431 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1432 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1433 and deals with signing/sealing details.
1434 ********************************************************************/
1436 struct rpc_api_pipe_req_state {
1437 struct tevent_context *ev;
1438 struct rpc_pipe_client *cli;
1439 uint8_t op_num;
1440 uint32_t call_id;
1441 const DATA_BLOB *req_data;
1442 const struct GUID *object_uuid;
1443 uint32_t req_data_sent;
1444 DATA_BLOB req_trailer;
1445 uint32_t req_trailer_sent;
1446 bool verify_bitmask1;
1447 bool verify_pcontext;
1448 DATA_BLOB rpc_out;
1449 DATA_BLOB reply_pdu;
1452 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1453 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1454 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1455 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1456 bool *is_last_frag);
1458 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1459 struct tevent_context *ev,
1460 struct rpc_pipe_client *cli,
1461 uint8_t op_num,
1462 const struct GUID *object_uuid,
1463 const DATA_BLOB *req_data)
1465 struct tevent_req *req, *subreq;
1466 struct rpc_api_pipe_req_state *state;
1467 NTSTATUS status;
1468 bool is_last_frag;
1470 req = tevent_req_create(mem_ctx, &state,
1471 struct rpc_api_pipe_req_state);
1472 if (req == NULL) {
1473 return NULL;
1475 state->ev = ev;
1476 state->cli = cli;
1477 state->op_num = op_num;
1478 state->object_uuid = object_uuid;
1479 state->req_data = req_data;
1480 state->call_id = ++cli->assoc->next_call_id;
1482 if (cli->conn->features.max_xmit_frag < DCERPC_REQUEST_LENGTH
1483 + RPC_MAX_SIGN_SIZE) {
1484 /* Server is screwed up ! */
1485 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1486 return tevent_req_post(req, ev);
1489 status = prepare_verification_trailer(state);
1490 if (tevent_req_nterror(req, status)) {
1491 return tevent_req_post(req, ev);
1494 status = prepare_next_frag(state, &is_last_frag);
1495 if (tevent_req_nterror(req, status)) {
1496 return tevent_req_post(req, ev);
1499 if (is_last_frag) {
1500 subreq = rpc_api_pipe_send(state, ev, state->cli,
1501 &state->rpc_out,
1502 DCERPC_PKT_RESPONSE,
1503 state->call_id);
1504 if (tevent_req_nomem(subreq, req)) {
1505 return tevent_req_post(req, ev);
1507 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1508 } else {
1509 subreq = rpc_write_send(state, ev, cli->conn->transport,
1510 state->rpc_out.data,
1511 state->rpc_out.length);
1512 if (tevent_req_nomem(subreq, req)) {
1513 return tevent_req_post(req, ev);
1515 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1516 req);
1518 return req;
1521 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1523 struct pipe_auth_data *a = state->cli->auth;
1524 struct dcerpc_sec_verification_trailer *t;
1525 struct ndr_push *ndr = NULL;
1526 enum ndr_err_code ndr_err;
1527 size_t align = 0;
1528 size_t pad = 0;
1530 if (a == NULL) {
1531 return NT_STATUS_OK;
1534 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1535 return NT_STATUS_OK;
1538 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1539 if (t == NULL) {
1540 return NT_STATUS_NO_MEMORY;
1543 if (!a->verified_bitmask1) {
1544 t->commands = talloc_realloc(t, t->commands,
1545 struct dcerpc_sec_vt,
1546 t->count.count + 1);
1547 if (t->commands == NULL) {
1548 return NT_STATUS_NO_MEMORY;
1550 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1551 .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
1552 .u.bitmask1 = (state->cli->conn->features.client_hdr_signing) ?
1553 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
1556 state->verify_bitmask1 = true;
1559 if (!state->cli->verified_pcontext) {
1560 t->commands = talloc_realloc(t, t->commands,
1561 struct dcerpc_sec_vt,
1562 t->count.count + 1);
1563 if (t->commands == NULL) {
1564 return NT_STATUS_NO_MEMORY;
1566 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1567 .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
1568 .u.pcontext.abstract_syntax =
1569 state->cli->table->syntax_id,
1570 .u.pcontext.transfer_syntax =
1571 state->cli->transfer_syntax,
1573 state->verify_pcontext = true;
1576 if (!a->hdr_signing) {
1577 t->commands = talloc_realloc(t, t->commands,
1578 struct dcerpc_sec_vt,
1579 t->count.count + 1);
1580 if (t->commands == NULL) {
1581 return NT_STATUS_NO_MEMORY;
1583 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1584 .command = DCERPC_SEC_VT_COMMAND_HEADER2,
1585 .u.header2.ptype = DCERPC_PKT_REQUEST,
1586 .u.header2.drep[0] = DCERPC_DREP_LE,
1587 .u.header2.call_id = state->call_id,
1588 .u.header2.context_id = state->cli->pres_context_id,
1589 .u.header2.opnum = state->op_num,
1593 if (t->count.count == 0) {
1594 TALLOC_FREE(t);
1595 return NT_STATUS_OK;
1598 t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
1600 if (DEBUGLEVEL >= 10) {
1601 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1604 ndr = ndr_push_init_ctx(state);
1605 if (ndr == NULL) {
1606 return NT_STATUS_NO_MEMORY;
1609 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1610 NDR_SCALARS | NDR_BUFFERS,
1612 TALLOC_FREE(t);
1613 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1614 return ndr_map_error2ntstatus(ndr_err);
1616 state->req_trailer = ndr_push_blob(ndr);
1618 align = state->req_data->length & 0x3;
1619 if (align > 0) {
1620 pad = 4 - align;
1622 if (pad > 0) {
1623 bool ok;
1624 uint8_t *p;
1625 const uint8_t zeros[4] = { 0, };
1627 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1628 if (!ok) {
1629 return NT_STATUS_NO_MEMORY;
1632 /* move the padding to the start */
1633 p = state->req_trailer.data;
1634 memmove(p + pad, p, state->req_trailer.length - pad);
1635 memset(p, 0, pad);
1638 return NT_STATUS_OK;
1641 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1642 bool *is_last_frag)
1644 size_t auth_len;
1645 size_t frag_len;
1646 uint8_t flags = 0;
1647 size_t pad_len;
1648 size_t data_left;
1649 size_t data_thistime;
1650 size_t trailer_left;
1651 size_t trailer_thistime = 0;
1652 size_t total_left;
1653 size_t total_thistime;
1654 NTSTATUS status;
1655 bool ok;
1656 union dcerpc_payload u;
1658 data_left = state->req_data->length - state->req_data_sent;
1659 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1660 total_left = data_left + trailer_left;
1661 if ((total_left < data_left) || (total_left < trailer_left)) {
1663 * overflow
1665 return NT_STATUS_INVALID_PARAMETER_MIX;
1668 status = dcerpc_guess_sizes(state->cli->auth,
1669 DCERPC_REQUEST_LENGTH, total_left,
1670 state->cli->conn->features.max_xmit_frag,
1671 &total_thistime,
1672 &frag_len, &auth_len, &pad_len);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 return status;
1677 if (state->req_data_sent == 0) {
1678 flags = DCERPC_PFC_FLAG_FIRST;
1681 if (total_thistime == total_left) {
1682 flags |= DCERPC_PFC_FLAG_LAST;
1685 data_thistime = MIN(total_thistime, data_left);
1686 if (data_thistime < total_thistime) {
1687 trailer_thistime = total_thistime - data_thistime;
1690 data_blob_free(&state->rpc_out);
1692 u = (union dcerpc_payload) {
1693 .request.alloc_hint = total_left,
1694 .request.context_id = state->cli->pres_context_id,
1695 .request.opnum = state->op_num,
1698 if (state->object_uuid) {
1699 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1700 u.request.object.object = *state->object_uuid;
1701 frag_len += ndr_size_GUID(state->object_uuid, 0);
1704 status = dcerpc_push_ncacn_packet(state,
1705 DCERPC_PKT_REQUEST,
1706 flags,
1707 auth_len,
1708 state->call_id,
1710 &state->rpc_out);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return status;
1715 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1716 * compute it right for requests because the auth trailer is missing
1717 * at this stage */
1718 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1720 if (data_thistime > 0) {
1721 /* Copy in the data. */
1722 ok = data_blob_append(NULL, &state->rpc_out,
1723 state->req_data->data + state->req_data_sent,
1724 data_thistime);
1725 if (!ok) {
1726 return NT_STATUS_NO_MEMORY;
1728 state->req_data_sent += data_thistime;
1731 if (trailer_thistime > 0) {
1732 /* Copy in the verification trailer. */
1733 ok = data_blob_append(NULL, &state->rpc_out,
1734 state->req_trailer.data + state->req_trailer_sent,
1735 trailer_thistime);
1736 if (!ok) {
1737 return NT_STATUS_NO_MEMORY;
1739 state->req_trailer_sent += trailer_thistime;
1742 switch (state->cli->auth->auth_level) {
1743 case DCERPC_AUTH_LEVEL_NONE:
1744 case DCERPC_AUTH_LEVEL_CONNECT:
1745 break;
1746 case DCERPC_AUTH_LEVEL_PACKET:
1747 case DCERPC_AUTH_LEVEL_INTEGRITY:
1748 case DCERPC_AUTH_LEVEL_PRIVACY:
1749 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1750 &state->rpc_out);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 return status;
1754 break;
1755 default:
1756 return NT_STATUS_INVALID_PARAMETER;
1759 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1761 return status;
1764 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1766 struct tevent_req *req = tevent_req_callback_data(
1767 subreq, struct tevent_req);
1768 struct rpc_api_pipe_req_state *state = tevent_req_data(
1769 req, struct rpc_api_pipe_req_state);
1770 NTSTATUS status;
1771 bool is_last_frag;
1773 status = rpc_write_recv(subreq);
1774 TALLOC_FREE(subreq);
1775 if (tevent_req_nterror(req, status)) {
1776 return;
1779 status = prepare_next_frag(state, &is_last_frag);
1780 if (tevent_req_nterror(req, status)) {
1781 return;
1784 if (is_last_frag) {
1785 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1786 &state->rpc_out,
1787 DCERPC_PKT_RESPONSE,
1788 state->call_id);
1789 if (tevent_req_nomem(subreq, req)) {
1790 return;
1792 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1793 } else {
1794 subreq = rpc_write_send(state, state->ev,
1795 state->cli->conn->transport,
1796 state->rpc_out.data,
1797 state->rpc_out.length);
1798 if (tevent_req_nomem(subreq, req)) {
1799 return;
1801 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1802 req);
1806 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1808 struct tevent_req *req = tevent_req_callback_data(
1809 subreq, struct tevent_req);
1810 struct rpc_api_pipe_req_state *state = tevent_req_data(
1811 req, struct rpc_api_pipe_req_state);
1812 NTSTATUS status;
1814 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1815 TALLOC_FREE(subreq);
1816 if (tevent_req_nterror(req, status)) {
1817 return;
1820 if (state->cli->auth == NULL) {
1821 tevent_req_done(req);
1822 return;
1825 if (state->verify_bitmask1) {
1826 state->cli->auth->verified_bitmask1 = true;
1829 if (state->verify_pcontext) {
1830 state->cli->verified_pcontext = true;
1833 tevent_req_done(req);
1836 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1837 DATA_BLOB *reply_pdu)
1839 struct rpc_api_pipe_req_state *state = tevent_req_data(
1840 req, struct rpc_api_pipe_req_state);
1841 NTSTATUS status;
1843 if (tevent_req_is_nterror(req, &status)) {
1845 * We always have to initialize to reply pdu, even if there is
1846 * none. The rpccli_* caller routines expect this.
1848 *reply_pdu = data_blob_null;
1849 return status;
1852 /* return data to caller and assign it ownership of memory */
1853 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1854 reply_pdu->length = state->reply_pdu.length;
1855 state->reply_pdu.length = 0;
1857 return NT_STATUS_OK;
1860 /****************************************************************************
1861 Check the rpc bind acknowledge response.
1862 ****************************************************************************/
1864 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1865 struct rpc_pipe_client *cli)
1867 const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
1868 uint32_t assoc_group_id =
1869 dcerpc_binding_get_assoc_group_id(cli->assoc->binding);
1870 struct dcerpc_ack_ctx ctx;
1871 bool equal;
1873 if (r->secondary_address_size == 0) {
1874 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
1877 if (assoc_group_id == 0) {
1878 NTSTATUS status;
1881 * We only capture the first assoc_group_id we're
1882 * getting.
1884 * Current samba releases may ignore the client value
1885 * and return a different assoc_group_id if the
1886 * client given one is not found in the preforked
1887 * process. This applies to the source4 netlogon,
1888 * which uses DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED.
1891 status = dcerpc_binding_set_assoc_group_id(cli->assoc->binding,
1892 r->assoc_group_id);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 return false;
1898 if (!cli->conn->features.bind_done) {
1900 * DCE-RPC 1.1 (c706) specifies
1901 * CONST_MUST_RCV_FRAG_SIZE as 1432
1904 if (r->max_xmit_frag < 1432) {
1905 return false;
1907 if (r->max_recv_frag < 1432) {
1908 return false;
1911 cli->conn->features.max_xmit_frag =
1912 MIN(cli->conn->features.max_xmit_frag, r->max_xmit_frag);
1913 cli->conn->features.max_recv_frag =
1914 MIN(cli->conn->features.max_recv_frag, r->max_recv_frag);
1916 cli->conn->features.bind_done = true;
1919 if (r->num_results < 1 || !r->ctx_list) {
1920 return false;
1923 ctx = r->ctx_list[0];
1925 /* check the transfer syntax */
1926 equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
1927 if (!equal) {
1928 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1929 return False;
1932 if (ctx.result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1933 DBG_NOTICE("bind denied result: %d reason: %x\n",
1934 ctx.result, ctx.reason.value);
1935 return false;
1938 if (r->num_results >= 2) {
1939 const struct dcerpc_ack_ctx *neg = &r->ctx_list[1];
1941 if (neg->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1942 cli->assoc->features.negotiated = neg->reason.negotiate;
1943 cli->assoc->features.negotiation_done = true;
1945 * consume presentation context used for bind time
1946 * feature negotiation
1948 cli->conn->next_pres_context_id++;
1949 } else {
1950 DBG_DEBUG("bind_time_feature failed - "
1951 "result: %d reason %x\n",
1952 neg->result, neg->reason.value);
1956 DEBUG(5,("check_bind_response: accepted!\n"));
1957 return True;
1960 /*******************************************************************
1961 Creates a DCE/RPC bind authentication response.
1962 This is the packet that is sent back to the server once we
1963 have received a BIND-ACK, to finish the third leg of
1964 the authentication handshake.
1965 ********************************************************************/
1967 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1968 struct rpc_pipe_client *cli,
1969 struct pipe_auth_data *auth,
1970 uint32_t rpc_call_id,
1971 DATA_BLOB *pauth_blob,
1972 DATA_BLOB *rpc_out)
1974 NTSTATUS status;
1975 union dcerpc_payload u = { .auth3._pad = 0, };
1977 status = dcerpc_push_dcerpc_auth(mem_ctx,
1978 auth->auth_type,
1979 auth->auth_level,
1980 0, /* auth_pad_length */
1981 auth->auth_context_id,
1982 pauth_blob,
1983 &u.auth3.auth_info);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 return status;
1988 status = dcerpc_push_ncacn_packet(mem_ctx,
1989 DCERPC_PKT_AUTH3,
1990 DCERPC_PFC_FLAG_FIRST |
1991 DCERPC_PFC_FLAG_LAST,
1992 pauth_blob->length,
1993 rpc_call_id,
1995 rpc_out);
1996 data_blob_free(&u.auth3.auth_info);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1999 return status;
2002 return NT_STATUS_OK;
2005 /*******************************************************************
2006 Creates a DCE/RPC bind alter context authentication request which
2007 may contain a spnego auth blob
2008 ********************************************************************/
2010 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
2011 struct pipe_auth_data *auth,
2012 uint32_t rpc_call_id,
2013 struct rpc_client_association *assoc,
2014 struct rpc_client_connection *conn,
2015 uint16_t pres_context_id,
2016 const struct ndr_syntax_id *abstract,
2017 const struct ndr_syntax_id *transfer,
2018 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2019 DATA_BLOB *rpc_out)
2021 DATA_BLOB auth_info;
2022 NTSTATUS status;
2024 status = dcerpc_push_dcerpc_auth(mem_ctx,
2025 auth->auth_type,
2026 auth->auth_level,
2027 0, /* auth_pad_length */
2028 auth->auth_context_id,
2029 pauth_blob,
2030 &auth_info);
2031 if (!NT_STATUS_IS_OK(status)) {
2032 return status;
2035 status = create_bind_or_alt_ctx_internal(mem_ctx,
2036 DCERPC_PKT_ALTER,
2037 rpc_call_id,
2038 assoc,
2039 conn,
2040 pres_context_id,
2041 abstract,
2042 transfer,
2043 &auth_info,
2044 rpc_out);
2045 data_blob_free(&auth_info);
2046 return status;
2049 /****************************************************************************
2050 Do an rpc bind.
2051 ****************************************************************************/
2053 struct rpc_pipe_bind_state {
2054 struct tevent_context *ev;
2055 struct rpc_pipe_client *cli;
2056 DATA_BLOB rpc_out;
2057 bool auth3;
2058 uint32_t rpc_call_id;
2061 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2062 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2063 struct rpc_pipe_bind_state *state,
2064 DATA_BLOB *credentials);
2065 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2066 struct rpc_pipe_bind_state *state,
2067 DATA_BLOB *credentials);
2069 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2070 struct tevent_context *ev,
2071 struct rpc_pipe_client *cli,
2072 struct pipe_auth_data *auth)
2074 struct tevent_req *req, *subreq;
2075 struct rpc_pipe_bind_state *state;
2076 struct cli_credentials *creds = NULL;
2077 const char *username = NULL;
2078 enum dcerpc_pkt_type rep_ptype = DCERPC_PKT_BIND_ACK;
2079 NTSTATUS status;
2081 if (cli->conn->features.bind_done) {
2082 rep_ptype = DCERPC_PKT_ALTER_RESP;
2085 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2086 if (req == NULL) {
2087 return NULL;
2090 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2091 rpccli_pipe_txt(talloc_tos(), cli),
2092 (unsigned int)auth->auth_type,
2093 (unsigned int)auth->auth_level ));
2095 state->ev = ev;
2096 state->cli = cli;
2097 state->rpc_call_id = ++cli->assoc->next_call_id;
2099 cli->auth = talloc_move(cli, &auth);
2100 if (cli->auth->auth_context_id == UINT32_MAX) {
2101 if (cli->conn->next_auth_context_id == UINT32_MAX) {
2102 tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
2103 return tevent_req_post(req, ev);
2105 cli->auth->auth_context_id = cli->conn->next_auth_context_id++;
2107 if (cli->pres_context_id == UINT16_MAX) {
2108 if (cli->conn->next_pres_context_id == UINT16_MAX) {
2109 tevent_req_nterror(req, NT_STATUS_RPC_NO_MORE_BINDINGS);
2110 return tevent_req_post(req, ev);
2112 cli->pres_context_id = cli->conn->next_pres_context_id++;
2115 cli->binding_handle = rpccli_bh_create(cli, NULL, cli->table);
2116 if (tevent_req_nomem(cli->binding_handle, req)) {
2117 return tevent_req_post(req, ev);
2120 creds = gensec_get_credentials(cli->auth->auth_ctx);
2121 username = cli_credentials_get_username(creds);
2122 cli->printer_username = talloc_strdup(cli, username);
2123 if (tevent_req_nomem(cli->printer_username, req)) {
2124 return tevent_req_post(req, ev);
2127 /* Marshall the outgoing data. */
2128 status = create_rpc_bind_req(state, cli,
2129 cli->auth,
2130 state->rpc_call_id,
2131 &cli->table->syntax_id,
2132 &cli->transfer_syntax,
2133 &state->rpc_out);
2135 if (!NT_STATUS_IS_OK(status) &&
2136 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2137 tevent_req_nterror(req, status);
2138 return tevent_req_post(req, ev);
2141 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2142 rep_ptype, state->rpc_call_id);
2143 if (tevent_req_nomem(subreq, req)) {
2144 return tevent_req_post(req, ev);
2146 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2147 return req;
2150 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2152 struct tevent_req *req = tevent_req_callback_data(
2153 subreq, struct tevent_req);
2154 struct rpc_pipe_bind_state *state = tevent_req_data(
2155 req, struct rpc_pipe_bind_state);
2156 struct pipe_auth_data *pauth = state->cli->auth;
2157 struct gensec_security *gensec_security;
2158 struct ncacn_packet *pkt = NULL;
2159 struct dcerpc_auth auth;
2160 DATA_BLOB auth_token = { .data = NULL };
2161 NTSTATUS status;
2163 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2164 TALLOC_FREE(subreq);
2165 if (tevent_req_nterror(req, status)) {
2166 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2167 rpccli_pipe_txt(talloc_tos(), state->cli),
2168 nt_errstr(status)));
2169 return;
2172 if (state->auth3) {
2173 tevent_req_done(req);
2174 return;
2177 if (!check_bind_response(&pkt->u.bind_ack, state->cli)) {
2178 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2179 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2180 return;
2183 if (state->cli->conn->features.client_hdr_signing &&
2184 pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)
2186 state->cli->conn->features.hdr_signing = true;
2189 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2190 /* Bind complete. */
2191 tevent_req_done(req);
2192 return;
2195 if (pkt->auth_length == 0) {
2196 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2197 return;
2200 pauth->hdr_signing = state->cli->conn->features.hdr_signing;
2202 /* get auth credentials */
2203 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
2204 &pkt->u.bind_ack.auth_info,
2205 &auth, NULL, true);
2206 if (tevent_req_nterror(req, status)) {
2207 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2208 nt_errstr(status)));
2209 return;
2212 if (auth.auth_type != pauth->auth_type) {
2213 DBG_ERR("Auth type %u mismatch expected %u.\n",
2214 auth.auth_type, pauth->auth_type);
2215 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2216 return;
2219 if (auth.auth_level != pauth->auth_level) {
2220 DBG_ERR("Auth level %u mismatch expected %u.\n",
2221 auth.auth_level, pauth->auth_level);
2222 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2223 return;
2226 if (auth.auth_context_id != pauth->auth_context_id) {
2227 DBG_ERR("Auth context id %"PRIu32" mismatch "
2228 "expected %"PRIu32".\n",
2229 auth.auth_context_id,
2230 pauth->auth_context_id);
2231 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2232 return;
2236 * For authenticated binds we may need to do 3 or 4 leg binds.
2239 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2240 /* Bind complete. */
2241 tevent_req_done(req);
2242 return;
2245 gensec_security = pauth->auth_ctx;
2247 status = gensec_update(gensec_security, state,
2248 auth.credentials, &auth_token);
2249 if (NT_STATUS_EQUAL(status,
2250 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2251 status = rpc_bind_next_send(req, state,
2252 &auth_token);
2253 } else if (NT_STATUS_IS_OK(status)) {
2254 if (pauth->hdr_signing) {
2255 gensec_want_feature(gensec_security,
2256 GENSEC_FEATURE_SIGN_PKT_HEADER);
2259 if (auth_token.length == 0) {
2260 /* Bind complete. */
2261 tevent_req_done(req);
2262 return;
2264 status = rpc_bind_finish_send(req, state,
2265 &auth_token);
2268 if (!NT_STATUS_IS_OK(status)) {
2269 tevent_req_nterror(req, status);
2271 return;
2274 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2275 struct rpc_pipe_bind_state *state,
2276 DATA_BLOB *auth_token)
2278 struct pipe_auth_data *auth = state->cli->auth;
2279 struct tevent_req *subreq;
2280 NTSTATUS status;
2282 /* Now prepare the alter context pdu. */
2283 data_blob_free(&state->rpc_out);
2285 status = create_rpc_alter_context(state, auth,
2286 state->rpc_call_id,
2287 state->cli->assoc,
2288 state->cli->conn,
2289 state->cli->pres_context_id,
2290 &state->cli->table->syntax_id,
2291 &state->cli->transfer_syntax,
2292 auth_token,
2293 &state->rpc_out);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 return status;
2298 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2299 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2300 state->rpc_call_id);
2301 if (subreq == NULL) {
2302 return NT_STATUS_NO_MEMORY;
2304 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2305 return NT_STATUS_OK;
2308 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2309 struct rpc_pipe_bind_state *state,
2310 DATA_BLOB *auth_token)
2312 struct pipe_auth_data *auth = state->cli->auth;
2313 struct tevent_req *subreq;
2314 NTSTATUS status;
2316 state->auth3 = true;
2318 /* Now prepare the auth3 context pdu. */
2319 data_blob_free(&state->rpc_out);
2321 status = create_rpc_bind_auth3(state, state->cli, auth,
2322 state->rpc_call_id,
2323 auth_token,
2324 &state->rpc_out);
2325 if (!NT_STATUS_IS_OK(status)) {
2326 return status;
2329 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2330 &state->rpc_out, DCERPC_PKT_AUTH3,
2331 state->rpc_call_id);
2332 if (subreq == NULL) {
2333 return NT_STATUS_NO_MEMORY;
2335 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2336 return NT_STATUS_OK;
2339 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2341 return tevent_req_simple_recv_ntstatus(req);
2344 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2345 struct pipe_auth_data *auth)
2347 TALLOC_CTX *frame = talloc_stackframe();
2348 struct tevent_context *ev;
2349 struct tevent_req *req;
2350 NTSTATUS status = NT_STATUS_OK;
2352 ev = samba_tevent_context_init(frame);
2353 if (ev == NULL) {
2354 status = NT_STATUS_NO_MEMORY;
2355 goto fail;
2358 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2359 if (req == NULL) {
2360 status = NT_STATUS_NO_MEMORY;
2361 goto fail;
2364 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2365 goto fail;
2368 status = rpc_pipe_bind_recv(req);
2369 fail:
2370 TALLOC_FREE(frame);
2371 return status;
2374 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2376 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2377 unsigned int timeout)
2379 if (rpc_cli == NULL) {
2380 return RPCCLI_DEFAULT_TIMEOUT;
2383 if (rpc_cli->binding_handle == NULL) {
2384 return RPCCLI_DEFAULT_TIMEOUT;
2387 return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2388 timeout);
2391 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2393 if (rpc_cli == NULL) {
2394 return false;
2397 if (rpc_cli->binding_handle == NULL) {
2398 return false;
2401 return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2404 struct rpccli_bh_state {
2405 struct rpc_pipe_client *rpc_cli;
2406 struct dcerpc_binding *binding;
2409 static const struct dcerpc_binding *rpccli_bh_get_binding(struct dcerpc_binding_handle *h)
2411 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2412 struct rpccli_bh_state);
2414 return hs->binding;
2417 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2419 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2420 struct rpccli_bh_state);
2421 struct rpc_cli_transport *transport = NULL;
2423 if (hs->rpc_cli == NULL) {
2424 return false;
2427 if (hs->rpc_cli->conn == NULL) {
2428 return false;
2431 transport = hs->rpc_cli->conn->transport;
2432 if (transport == NULL) {
2433 return false;
2436 if (transport->is_connected == NULL) {
2437 return false;
2440 return transport->is_connected(transport->priv);
2443 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2444 uint32_t timeout)
2446 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2447 struct rpccli_bh_state);
2448 struct rpc_cli_transport *transport = NULL;
2449 unsigned int old;
2451 if (hs->rpc_cli->conn == NULL) {
2452 return RPCCLI_DEFAULT_TIMEOUT;
2455 transport = hs->rpc_cli->conn->transport;
2456 if (transport == NULL) {
2457 return RPCCLI_DEFAULT_TIMEOUT;
2460 if (transport->set_timeout == NULL) {
2461 return RPCCLI_DEFAULT_TIMEOUT;
2464 old = transport->set_timeout(transport->priv, timeout);
2465 if (old == 0) {
2466 return RPCCLI_DEFAULT_TIMEOUT;
2469 return old;
2472 static NTSTATUS rpccli_bh_transport_session_key(struct dcerpc_binding_handle *h,
2473 TALLOC_CTX *mem_ctx,
2474 DATA_BLOB *session_key)
2476 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2477 struct rpccli_bh_state);
2478 DATA_BLOB sk = { .length = 0, };
2480 if (hs->rpc_cli == NULL) {
2481 return NT_STATUS_NO_USER_SESSION_KEY;
2484 if (hs->rpc_cli->conn == NULL) {
2485 return NT_STATUS_NO_USER_SESSION_KEY;
2488 if (hs->rpc_cli->conn->transport_session_key.length == 0) {
2489 return NT_STATUS_NO_USER_SESSION_KEY;
2492 sk = hs->rpc_cli->conn->transport_session_key;
2493 sk.length = MIN(sk.length, 16);
2495 *session_key = data_blob_dup_talloc(mem_ctx, sk);
2496 if (session_key->length != sk.length) {
2497 return NT_STATUS_NO_MEMORY;
2499 talloc_keep_secret(session_key->data);
2500 return NT_STATUS_OK;
2503 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2504 enum dcerpc_AuthType *auth_type,
2505 enum dcerpc_AuthLevel *auth_level)
2507 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2508 struct rpccli_bh_state);
2510 if (hs->rpc_cli == NULL) {
2511 return;
2514 if (hs->rpc_cli->auth == NULL) {
2515 return;
2518 *auth_type = hs->rpc_cli->auth->auth_type;
2519 *auth_level = hs->rpc_cli->auth->auth_level;
2522 static NTSTATUS rpccli_bh_auth_session_key(struct dcerpc_binding_handle *h,
2523 TALLOC_CTX *mem_ctx,
2524 DATA_BLOB *session_key)
2526 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2527 struct rpccli_bh_state);
2528 struct pipe_auth_data *auth = NULL;
2529 NTSTATUS status;
2531 if (hs->rpc_cli == NULL) {
2532 return NT_STATUS_NO_USER_SESSION_KEY;
2535 if (hs->rpc_cli->auth == NULL) {
2536 return NT_STATUS_NO_USER_SESSION_KEY;
2539 auth = hs->rpc_cli->auth;
2541 if (auth->auth_type == DCERPC_AUTH_TYPE_NONE) {
2542 return NT_STATUS_NO_USER_SESSION_KEY;
2545 if (auth->auth_ctx == NULL) {
2546 return NT_STATUS_NO_USER_SESSION_KEY;
2549 status = gensec_session_key(auth->auth_ctx,
2550 mem_ctx,
2551 session_key);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 return status;
2556 talloc_keep_secret(session_key->data);
2557 return NT_STATUS_OK;
2560 struct rpccli_bh_raw_call_state {
2561 DATA_BLOB in_data;
2562 DATA_BLOB out_data;
2563 uint32_t out_flags;
2566 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2568 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2569 struct tevent_context *ev,
2570 struct dcerpc_binding_handle *h,
2571 const struct GUID *object,
2572 uint32_t opnum,
2573 uint32_t in_flags,
2574 const uint8_t *in_data,
2575 size_t in_length)
2577 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2578 struct rpccli_bh_state);
2579 struct tevent_req *req;
2580 struct rpccli_bh_raw_call_state *state;
2581 bool ok;
2582 struct tevent_req *subreq;
2584 req = tevent_req_create(mem_ctx, &state,
2585 struct rpccli_bh_raw_call_state);
2586 if (req == NULL) {
2587 return NULL;
2589 state->in_data.data = discard_const_p(uint8_t, in_data);
2590 state->in_data.length = in_length;
2592 ok = rpccli_bh_is_connected(h);
2593 if (!ok) {
2594 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2595 return tevent_req_post(req, ev);
2598 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2599 opnum, object, &state->in_data);
2600 if (tevent_req_nomem(subreq, req)) {
2601 return tevent_req_post(req, ev);
2603 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2605 return req;
2608 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2610 struct tevent_req *req =
2611 tevent_req_callback_data(subreq,
2612 struct tevent_req);
2613 struct rpccli_bh_raw_call_state *state =
2614 tevent_req_data(req,
2615 struct rpccli_bh_raw_call_state);
2616 NTSTATUS status;
2618 state->out_flags = 0;
2620 /* TODO: support bigendian responses */
2622 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2623 TALLOC_FREE(subreq);
2624 if (tevent_req_nterror(req, status)) {
2625 return;
2628 tevent_req_done(req);
2631 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2632 TALLOC_CTX *mem_ctx,
2633 uint8_t **out_data,
2634 size_t *out_length,
2635 uint32_t *out_flags)
2637 struct rpccli_bh_raw_call_state *state =
2638 tevent_req_data(req,
2639 struct rpccli_bh_raw_call_state);
2640 NTSTATUS status;
2642 if (tevent_req_is_nterror(req, &status)) {
2643 tevent_req_received(req);
2644 return status;
2647 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2648 *out_length = state->out_data.length;
2649 *out_flags = state->out_flags;
2650 tevent_req_received(req);
2651 return NT_STATUS_OK;
2654 struct rpccli_bh_disconnect_state {
2655 uint8_t _dummy;
2658 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2659 struct tevent_context *ev,
2660 struct dcerpc_binding_handle *h)
2662 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2663 struct rpccli_bh_state);
2664 struct tevent_req *req;
2665 struct rpccli_bh_disconnect_state *state;
2666 bool ok;
2668 req = tevent_req_create(mem_ctx, &state,
2669 struct rpccli_bh_disconnect_state);
2670 if (req == NULL) {
2671 return NULL;
2674 ok = rpccli_bh_is_connected(h);
2675 if (!ok) {
2676 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2677 return tevent_req_post(req, ev);
2681 * TODO: do a real async disconnect ...
2683 * For now we do it sync...
2685 TALLOC_FREE(hs->rpc_cli->conn);
2686 hs->rpc_cli = NULL;
2688 tevent_req_done(req);
2689 return tevent_req_post(req, ev);
2692 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2694 return tevent_req_simple_recv_ntstatus(req);
2697 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2699 return true;
2702 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2703 ndr_flags_type ndr_flags,
2704 const void *_struct_ptr,
2705 const struct ndr_interface_call *call)
2707 void *struct_ptr = discard_const(_struct_ptr);
2709 if (DEBUGLEVEL < 10) {
2710 return;
2713 if (ndr_flags & NDR_IN) {
2714 ndr_print_function_debug(call->ndr_print,
2715 call->name,
2716 ndr_flags,
2717 struct_ptr);
2719 if (ndr_flags & NDR_OUT) {
2720 ndr_print_function_debug(call->ndr_print,
2721 call->name,
2722 ndr_flags,
2723 struct_ptr);
2727 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2728 .name = "rpccli",
2729 .get_binding = rpccli_bh_get_binding,
2730 .is_connected = rpccli_bh_is_connected,
2731 .set_timeout = rpccli_bh_set_timeout,
2732 .transport_session_key = rpccli_bh_transport_session_key,
2733 .auth_info = rpccli_bh_auth_info,
2734 .auth_session_key = rpccli_bh_auth_session_key,
2735 .raw_call_send = rpccli_bh_raw_call_send,
2736 .raw_call_recv = rpccli_bh_raw_call_recv,
2737 .disconnect_send = rpccli_bh_disconnect_send,
2738 .disconnect_recv = rpccli_bh_disconnect_recv,
2740 .ref_alloc = rpccli_bh_ref_alloc,
2741 .do_ndr_print = rpccli_bh_do_ndr_print,
2744 /* initialise a rpc_pipe_client binding handle */
2745 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2746 const struct GUID *object,
2747 const struct ndr_interface_table *table)
2749 struct dcerpc_binding_handle *h = NULL;
2750 struct rpccli_bh_state *hs = NULL;
2751 struct dcerpc_binding *b = NULL;
2752 uint32_t a_flags = 0;
2753 uint32_t c_flags = 0;
2754 NTSTATUS status;
2756 if (c->conn->features.hdr_signing) {
2757 a_flags |= DCERPC_HEADER_SIGNING;
2758 } else {
2759 c_flags |= DCERPC_HEADER_SIGNING;
2762 switch (c->auth->auth_type) {
2763 case DCERPC_AUTH_TYPE_KRB5:
2764 a_flags |= DCERPC_AUTH_KRB5;
2765 c_flags |= DCERPC_AUTH_NTLM;
2766 c_flags |= DCERPC_AUTH_SPNEGO;
2767 c_flags |= DCERPC_SCHANNEL;
2768 break;
2769 case DCERPC_AUTH_TYPE_NTLMSSP:
2770 c_flags |= DCERPC_AUTH_KRB5;
2771 a_flags |= DCERPC_AUTH_NTLM;
2772 c_flags |= DCERPC_AUTH_SPNEGO;
2773 c_flags |= DCERPC_SCHANNEL;
2774 break;
2775 case DCERPC_AUTH_TYPE_SPNEGO:
2776 c_flags |= DCERPC_AUTH_KRB5;
2777 c_flags |= DCERPC_AUTH_NTLM;
2778 a_flags |= DCERPC_AUTH_SPNEGO;
2779 c_flags |= DCERPC_SCHANNEL;
2780 break;
2781 case DCERPC_AUTH_TYPE_SCHANNEL:
2782 c_flags |= DCERPC_AUTH_KRB5;
2783 c_flags |= DCERPC_AUTH_NTLM;
2784 c_flags |= DCERPC_AUTH_SPNEGO;
2785 a_flags |= DCERPC_SCHANNEL;
2786 break;
2787 default:
2788 c_flags |= DCERPC_AUTH_KRB5;
2789 c_flags |= DCERPC_AUTH_NTLM;
2790 c_flags |= DCERPC_AUTH_SPNEGO;
2791 c_flags |= DCERPC_SCHANNEL;
2792 break;
2795 if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_PRIVACY) {
2796 a_flags |= DCERPC_SEAL;
2797 c_flags |= DCERPC_SIGN;
2798 c_flags |= DCERPC_CONNECT;
2799 } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
2800 c_flags |= DCERPC_SEAL;
2801 a_flags |= DCERPC_SIGN;
2802 c_flags |= DCERPC_CONNECT;
2803 } else if (c->auth->auth_level >= DCERPC_AUTH_LEVEL_CONNECT) {
2804 c_flags |= DCERPC_SEAL;
2805 c_flags |= DCERPC_SIGN;
2806 a_flags |= DCERPC_CONNECT;
2807 } else {
2808 c_flags |= DCERPC_SEAL;
2809 c_flags |= DCERPC_SIGN;
2810 c_flags |= DCERPC_CONNECT;
2813 h = dcerpc_binding_handle_create(c,
2814 &rpccli_bh_ops,
2815 object,
2816 table,
2817 &hs,
2818 struct rpccli_bh_state,
2819 __location__);
2820 if (h == NULL) {
2821 return NULL;
2823 hs->rpc_cli = c;
2825 b = dcerpc_binding_dup(h, c->assoc->binding);
2826 if (b == NULL) {
2827 TALLOC_FREE(h);
2828 return NULL;
2830 status = dcerpc_binding_set_abstract_syntax(b, &table->syntax_id);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 TALLOC_FREE(h);
2833 return NULL;
2835 status = dcerpc_binding_set_flags(b, a_flags, c_flags);
2836 if (!NT_STATUS_IS_OK(status)) {
2837 TALLOC_FREE(h);
2838 return NULL;
2841 hs->binding = b;
2843 return h;
2846 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2847 struct pipe_auth_data **presult)
2849 struct pipe_auth_data *result;
2850 struct auth_generic_state *auth_generic_ctx;
2851 NTSTATUS status;
2853 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2854 if (result == NULL) {
2855 return NT_STATUS_NO_MEMORY;
2858 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2859 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2860 /* rpc_pipe_bind_send should allocate an id... */
2861 result->auth_context_id = UINT32_MAX;
2863 status = auth_generic_client_prepare(result,
2864 &auth_generic_ctx);
2865 if (!NT_STATUS_IS_OK(status)) {
2866 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2867 nt_errstr(status)));
2870 status = auth_generic_set_username(auth_generic_ctx, "");
2871 if (!NT_STATUS_IS_OK(status)) {
2872 DEBUG(1, ("Failed to set username: %s\n",
2873 nt_errstr(status)));
2876 status = auth_generic_set_domain(auth_generic_ctx, "");
2877 if (!NT_STATUS_IS_OK(status)) {
2878 DEBUG(1, ("Failed to set domain: %s\n",
2879 nt_errstr(status)));
2880 return status;
2883 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2884 auth_generic_ctx->credentials);
2885 if (!NT_STATUS_IS_OK(status)) {
2886 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2887 nt_errstr(status)));
2888 return status;
2890 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2891 auth_generic_ctx->credentials = NULL;
2893 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2894 talloc_free(auth_generic_ctx);
2895 *presult = result;
2896 return NT_STATUS_OK;
2899 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2900 enum dcerpc_AuthType auth_type,
2901 enum dcerpc_AuthLevel auth_level,
2902 const char *server,
2903 const char *target_service,
2904 const char *domain,
2905 const char *username,
2906 const char *password,
2907 enum credentials_use_kerberos use_kerberos,
2908 struct netlogon_creds_CredentialState *creds,
2909 struct pipe_auth_data **presult)
2911 struct auth_generic_state *auth_generic_ctx;
2912 struct pipe_auth_data *result;
2913 NTSTATUS status;
2915 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2916 if (result == NULL) {
2917 return NT_STATUS_NO_MEMORY;
2920 result->auth_type = auth_type;
2921 result->auth_level = auth_level;
2922 /* rpc_pipe_bind_send should allocate an id... */
2923 result->auth_context_id = UINT32_MAX;
2925 status = auth_generic_client_prepare(result,
2926 &auth_generic_ctx);
2927 if (!NT_STATUS_IS_OK(status)) {
2928 goto fail;
2931 status = auth_generic_set_username(auth_generic_ctx, username);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 goto fail;
2936 status = auth_generic_set_domain(auth_generic_ctx, domain);
2937 if (!NT_STATUS_IS_OK(status)) {
2938 goto fail;
2941 status = auth_generic_set_password(auth_generic_ctx, password);
2942 if (!NT_STATUS_IS_OK(status)) {
2943 goto fail;
2946 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 goto fail;
2951 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 goto fail;
2956 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
2957 use_kerberos,
2958 CRED_SPECIFIED);
2959 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2961 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 goto fail;
2966 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2967 talloc_free(auth_generic_ctx);
2968 *presult = result;
2969 return NT_STATUS_OK;
2971 fail:
2972 TALLOC_FREE(result);
2973 return status;
2976 /* This routine steals the creds pointer that is passed in */
2977 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2978 enum dcerpc_AuthType auth_type,
2979 enum dcerpc_AuthLevel auth_level,
2980 const char *server,
2981 const char *target_service,
2982 struct cli_credentials *creds,
2983 struct pipe_auth_data **presult)
2985 struct auth_generic_state *auth_generic_ctx;
2986 struct pipe_auth_data *result;
2987 NTSTATUS status;
2989 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2990 if (result == NULL) {
2991 return NT_STATUS_NO_MEMORY;
2994 result->auth_type = auth_type;
2995 result->auth_level = auth_level;
2996 /* rpc_pipe_bind_send should allocate an id... */
2997 result->auth_context_id = UINT32_MAX;
2999 status = auth_generic_client_prepare(result,
3000 &auth_generic_ctx);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 goto fail;
3005 status = auth_generic_set_creds(auth_generic_ctx, creds);
3006 if (!NT_STATUS_IS_OK(status)) {
3007 goto fail;
3010 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
3011 if (!NT_STATUS_IS_OK(status)) {
3012 goto fail;
3015 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
3016 if (!NT_STATUS_IS_OK(status)) {
3017 goto fail;
3020 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 goto fail;
3025 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
3026 talloc_free(auth_generic_ctx);
3027 *presult = result;
3028 return NT_STATUS_OK;
3030 fail:
3031 TALLOC_FREE(result);
3032 return status;
3035 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
3036 struct pipe_auth_data **presult)
3038 return rpccli_generic_bind_data(mem_ctx,
3039 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
3040 DCERPC_AUTH_LEVEL_CONNECT,
3041 NULL, /* server */
3042 "host", /* target_service */
3043 NAME_NT_AUTHORITY, /* domain */
3044 "SYSTEM",
3045 NULL, /* password */
3046 CRED_USE_KERBEROS_DISABLED,
3047 NULL, /* netlogon_creds_CredentialState */
3048 presult);
3052 * Create an rpc pipe client struct, connecting to a tcp port.
3054 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx,
3055 const struct rpc_client_association *assoc,
3056 struct rpc_client_connection **pconn)
3058 struct rpc_client_connection *conn = NULL;
3059 enum dcerpc_transport_t transport;
3060 const char *endpoint = NULL;
3061 uint16_t port;
3062 NTSTATUS status;
3063 int fd;
3065 transport = dcerpc_binding_get_transport(assoc->binding);
3066 if (transport != NCACN_IP_TCP) {
3067 return NT_STATUS_RPC_WRONG_KIND_OF_BINDING;
3070 endpoint = dcerpc_binding_get_string_option(assoc->binding,
3071 "endpoint");
3072 if (endpoint == NULL) {
3073 return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT;
3075 port = (uint16_t)atoi(endpoint);
3076 if (port == 0) {
3077 return NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT;
3080 status = rpc_client_connection_create(mem_ctx,
3081 assoc,
3082 DCERPC_FRAG_MAX_SIZE,
3083 &conn);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 return status;
3088 status = open_socket_out(&assoc->addr.u.ss, port, 60*1000, &fd);
3089 if (!NT_STATUS_IS_OK(status)) {
3090 TALLOC_FREE(conn);
3091 return status;
3093 set_socket_options(fd, lp_socket_options());
3095 status = rpc_transport_sock_init(conn, fd, &conn->transport);
3096 if (!NT_STATUS_IS_OK(status)) {
3097 close(fd);
3098 TALLOC_FREE(conn);
3099 return status;
3102 conn->transport->transport = NCACN_IP_TCP;
3104 *pconn = conn;
3105 return NT_STATUS_OK;
3108 static NTSTATUS rpccli_epm_map_binding(
3109 struct dcerpc_binding_handle *epm_connection,
3110 struct dcerpc_binding *binding,
3111 TALLOC_CTX *mem_ctx,
3112 char **pendpoint)
3114 TALLOC_CTX *frame = talloc_stackframe();
3115 enum dcerpc_transport_t transport =
3116 dcerpc_binding_get_transport(binding);
3117 enum dcerpc_transport_t res_transport;
3118 struct dcerpc_binding *res_binding = NULL;
3119 struct epm_twr_t *map_tower = NULL;
3120 struct epm_twr_p_t res_towers = { .twr = NULL };
3121 struct policy_handle *entry_handle = NULL;
3122 uint32_t num_towers = 0;
3123 const uint32_t max_towers = 1;
3124 const char *endpoint = NULL;
3125 char *tmp = NULL;
3126 uint32_t result;
3127 NTSTATUS status;
3129 map_tower = talloc_zero(frame, struct epm_twr_t);
3130 if (map_tower == NULL) {
3131 goto nomem;
3134 status = dcerpc_binding_build_tower(
3135 frame, binding, &(map_tower->tower));
3136 if (!NT_STATUS_IS_OK(status)) {
3137 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
3138 nt_errstr(status));
3139 goto done;
3142 res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
3143 if (res_towers.twr == NULL) {
3144 goto nomem;
3147 entry_handle = talloc_zero(frame, struct policy_handle);
3148 if (entry_handle == NULL) {
3149 goto nomem;
3152 status = dcerpc_epm_Map(
3153 epm_connection,
3154 frame,
3155 NULL,
3156 map_tower,
3157 entry_handle,
3158 max_towers,
3159 &num_towers,
3160 &res_towers,
3161 &result);
3163 if (!NT_STATUS_IS_OK(status)) {
3164 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
3165 goto done;
3168 if (result != EPMAPPER_STATUS_OK) {
3169 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
3170 status = NT_STATUS_NOT_FOUND;
3171 goto done;
3174 if (num_towers != 1) {
3175 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
3176 num_towers);
3177 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3178 goto done;
3181 status = dcerpc_binding_from_tower(
3182 frame, &(res_towers.twr->tower), &res_binding);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
3185 nt_errstr(status));
3186 goto done;
3189 res_transport = dcerpc_binding_get_transport(res_binding);
3190 if (res_transport != transport) {
3191 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
3192 "expected %d\n",
3193 (int)res_transport,
3194 (int)transport);
3195 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3196 goto done;
3199 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
3200 if (endpoint == NULL) {
3201 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
3202 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
3203 goto done;
3206 tmp = talloc_strdup(mem_ctx, endpoint);
3207 if (tmp == NULL) {
3208 goto nomem;
3210 *pendpoint = tmp;
3212 status = NT_STATUS_OK;
3213 goto done;
3215 nomem:
3216 status = NT_STATUS_NO_MEMORY;
3217 done:
3218 TALLOC_FREE(frame);
3219 return status;
3222 static NTSTATUS rpccli_epm_map_interface(
3223 struct dcerpc_binding_handle *epm_connection,
3224 enum dcerpc_transport_t transport,
3225 const struct ndr_syntax_id *iface,
3226 TALLOC_CTX *mem_ctx,
3227 char **pendpoint)
3229 struct dcerpc_binding *binding = NULL;
3230 char *endpoint = NULL;
3231 NTSTATUS status;
3233 status = dcerpc_parse_binding(mem_ctx, "", &binding);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
3236 nt_errstr(status));
3237 goto done;
3240 status = dcerpc_binding_set_transport(binding, transport);
3241 if (!NT_STATUS_IS_OK(status)) {
3242 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
3243 nt_errstr(status));
3244 goto done;
3247 status = dcerpc_binding_set_abstract_syntax(binding, iface);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
3250 nt_errstr(status));
3251 goto done;
3254 status = rpccli_epm_map_binding(
3255 epm_connection, binding, mem_ctx, &endpoint);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
3258 nt_errstr(status));
3259 goto done;
3261 *pendpoint = endpoint;
3263 done:
3264 TALLOC_FREE(binding);
3265 return status;
3269 * Determine the tcp port on which a dcerpc interface is listening
3270 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3271 * target host.
3273 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3274 const struct samba_sockaddr *saddr,
3275 const struct ndr_interface_table *table,
3276 uint16_t *pport)
3278 TALLOC_CTX *frame = talloc_stackframe();
3279 const char *epm_ep = NULL;
3280 struct rpc_client_association *epm_assoc = NULL;
3281 struct rpc_client_connection *epm_conn = NULL;
3282 struct rpc_pipe_client *epm_pipe = NULL;
3283 struct pipe_auth_data *epm_auth = NULL;
3284 char *endpoint = NULL;
3285 uint16_t port = 0;
3286 NTSTATUS status;
3288 endpoint = dcerpc_default_transport_endpoint(frame,
3289 NCACN_IP_TCP,
3290 table);
3291 if (endpoint != NULL) {
3292 port = (uint16_t)atoi(endpoint);
3295 if (port != 0) {
3296 *pport = port;
3297 TALLOC_FREE(frame);
3298 return NT_STATUS_OK;
3301 epm_ep = dcerpc_default_transport_endpoint(frame,
3302 NCACN_IP_TCP,
3303 &ndr_table_epmapper);
3304 if (epm_ep == NULL) {
3305 TALLOC_FREE(frame);
3306 return NT_STATUS_RPC_INTERNAL_ERROR;
3309 status = rpc_client_association_create(frame,
3310 default_bt_features,
3311 DCERPC_PROPOSE_HEADER_SIGNING,
3312 host,
3313 NCACN_IP_TCP,
3314 saddr,
3315 epm_ep,
3316 &epm_assoc);
3317 if (!NT_STATUS_IS_OK(status)) {
3318 TALLOC_FREE(frame);
3319 return status;
3322 /* open the connection to the endpoint mapper */
3323 status = rpc_pipe_open_tcp_port(frame, epm_assoc, &epm_conn);
3324 if (!NT_STATUS_IS_OK(status)) {
3325 TALLOC_FREE(frame);
3326 return status;
3329 status = rpccli_anon_bind_data(frame, &epm_auth);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 TALLOC_FREE(frame);
3332 return status;
3335 status = rpc_pipe_wrap_create(&ndr_table_epmapper,
3336 NULL,
3337 &epm_assoc,
3338 &epm_conn,
3339 frame,
3340 &epm_pipe);
3341 if (!NT_STATUS_IS_OK(status)) {
3342 TALLOC_FREE(frame);
3343 return status;
3346 status = rpc_pipe_bind(epm_pipe, epm_auth);
3347 if (!NT_STATUS_IS_OK(status)) {
3348 TALLOC_FREE(frame);
3349 return status;
3352 status = rpccli_epm_map_interface(
3353 epm_pipe->binding_handle,
3354 NCACN_IP_TCP,
3355 &table->syntax_id,
3356 frame,
3357 &endpoint);
3358 if (!NT_STATUS_IS_OK(status)) {
3359 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3360 nt_errstr(status));
3361 TALLOC_FREE(frame);
3362 return status;
3365 *pport = (uint16_t)atoi(endpoint);
3366 TALLOC_FREE(frame);
3367 return NT_STATUS_OK;
3370 static NTSTATUS rpc_pipe_get_ncalrpc_name(
3371 const struct ndr_syntax_id *iface,
3372 TALLOC_CTX *mem_ctx,
3373 char **psocket_name)
3375 TALLOC_CTX *frame = talloc_stackframe();
3376 struct rpc_pipe_client *epm_pipe = NULL;
3377 struct pipe_auth_data *auth = NULL;
3378 NTSTATUS status = NT_STATUS_OK;
3379 bool is_epm;
3381 is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
3382 if (is_epm) {
3383 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
3384 if (endpoint == NULL) {
3385 status = NT_STATUS_NO_MEMORY;
3386 goto done;
3388 *psocket_name = endpoint;
3389 goto done;
3392 status = rpc_pipe_open_ncalrpc(
3393 frame, &ndr_table_epmapper, &epm_pipe);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
3396 nt_errstr(status));
3397 goto done;
3400 status = rpccli_anon_bind_data(epm_pipe, &auth);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3403 nt_errstr(status));
3404 goto done;
3407 status = rpc_pipe_bind(epm_pipe, auth);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3410 goto done;
3413 status = rpccli_epm_map_interface(
3414 epm_pipe->binding_handle,
3415 NCALRPC,
3416 iface,
3417 mem_ctx,
3418 psocket_name);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3421 nt_errstr(status));
3424 done:
3425 TALLOC_FREE(frame);
3426 return status;
3429 /********************************************************************
3430 Create a rpc pipe client struct, connecting to a unix domain socket
3431 ********************************************************************/
3432 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
3433 const struct ndr_interface_table *table,
3434 struct rpc_pipe_client **presult)
3436 TALLOC_CTX *frame = talloc_stackframe();
3437 char *myname = NULL;
3438 char *socket_name = NULL;
3439 struct samba_sockaddr saddr = {
3440 .sa_socklen = sizeof(struct sockaddr_un),
3441 .u = {
3442 .un = {
3443 .sun_family = AF_UNIX,
3447 struct rpc_client_association *assoc = NULL;
3448 struct rpc_client_connection *conn = NULL;
3449 struct rpc_pipe_client *result = NULL;
3450 int pathlen;
3451 NTSTATUS status;
3452 int fd = -1;
3454 myname = get_myname(frame);
3455 if (myname == NULL) {
3456 TALLOC_FREE(frame);
3457 return NT_STATUS_NO_MEMORY;
3460 status = rpc_pipe_get_ncalrpc_name(&table->syntax_id,
3461 frame,
3462 &socket_name);
3463 if (!NT_STATUS_IS_OK(status)) {
3464 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
3465 nt_errstr(status));
3466 TALLOC_FREE(frame);
3467 return status;
3470 pathlen = snprintf(
3471 saddr.u.un.sun_path,
3472 sizeof(saddr.u.un.sun_path),
3473 "%s/%s",
3474 lp_ncalrpc_dir(),
3475 socket_name);
3476 if ((pathlen < 0) || ((size_t)pathlen >= sizeof(saddr.u.un.sun_path))) {
3477 DBG_DEBUG("socket_path for %s too long\n", socket_name);
3478 TALLOC_FREE(frame);
3479 return NT_STATUS_NAME_TOO_LONG;
3481 TALLOC_FREE(socket_name);
3483 status = rpc_client_association_create(mem_ctx,
3484 0, /* no client_features */
3485 0, /* flags */
3486 myname,
3487 NCALRPC,
3488 &saddr,
3489 socket_name,
3490 &assoc);
3491 if (!NT_STATUS_IS_OK(status)) {
3492 TALLOC_FREE(frame);
3493 return status;
3495 talloc_steal(frame, assoc);
3497 status = rpc_client_connection_create(mem_ctx,
3498 assoc,
3499 DCERPC_FRAG_MAX_SIZE,
3500 &conn);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 TALLOC_FREE(frame);
3503 return status;
3505 talloc_steal(frame, conn);
3507 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3508 if (fd == -1) {
3509 status = map_nt_error_from_unix(errno);
3510 TALLOC_FREE(frame);
3511 return status;
3514 if (connect(fd, &saddr.u.sa, saddr.sa_socklen) == -1) {
3515 status = map_nt_error_from_unix(errno);
3516 close(fd);
3517 DBG_WARNING("connect(%s) failed: %s - %s\n",
3518 saddr.u.un.sun_path,
3519 strerror(errno), nt_errstr(status));
3520 TALLOC_FREE(frame);
3521 return status;
3524 status = rpc_transport_sock_init(conn, fd, &conn->transport);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 close(fd);
3527 TALLOC_FREE(frame);
3528 return status;
3530 fd = -1;
3532 conn->transport->transport = NCALRPC;
3534 status = rpc_pipe_wrap_create(table,
3535 NULL,
3536 &assoc,
3537 &conn,
3538 mem_ctx,
3539 &result);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 TALLOC_FREE(frame);
3542 return status;
3545 *presult = result;
3546 TALLOC_FREE(frame);
3547 return NT_STATUS_OK;
3550 NTSTATUS rpc_pipe_open_local_np(
3551 TALLOC_CTX *mem_ctx,
3552 const struct ndr_interface_table *table,
3553 const char *remote_client_name,
3554 const struct tsocket_address *remote_client_addr,
3555 const char *local_server_name,
3556 const struct tsocket_address *local_server_addr,
3557 const struct auth_session_info *session_info,
3558 struct rpc_pipe_client **presult)
3560 TALLOC_CTX *frame = talloc_stackframe();
3561 struct rpc_client_association *assoc = NULL;
3562 struct rpc_client_connection *conn = NULL;
3563 struct rpc_pipe_client *result = NULL;
3564 struct pipe_auth_data *auth = NULL;
3565 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3566 const char *pipe_name = NULL;
3567 struct tstream_context *npa_stream = NULL;
3568 NTSTATUS status = NT_STATUS_NO_MEMORY;
3569 int ret;
3571 pipe_name = dcerpc_default_transport_endpoint(frame,
3572 NCACN_NP,
3573 table);
3574 if (pipe_name == NULL) {
3575 DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
3576 TALLOC_FREE(frame);
3577 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3580 if (local_server_name == NULL) {
3581 local_server_name = get_myname(result);
3584 if (local_server_addr != NULL) {
3585 saddr.sa_socklen = tsocket_address_bsd_sockaddr(local_server_addr,
3586 &saddr.u.sa,
3587 sizeof(saddr.u.ss));
3588 if (saddr.sa_socklen == -1) {
3589 status = map_nt_error_from_unix(errno);
3590 TALLOC_FREE(frame);
3591 return status;
3595 status = rpc_client_association_create(mem_ctx,
3596 0, /* no client_features */
3597 0, /* flags */
3598 local_server_name,
3599 NCACN_NP,
3600 &saddr,
3601 pipe_name,
3602 &assoc);
3603 if (!NT_STATUS_IS_OK(status)) {
3604 TALLOC_FREE(frame);
3605 return status;
3607 talloc_steal(frame, assoc);
3609 status = rpc_client_connection_create(mem_ctx,
3610 assoc,
3611 DCERPC_FRAG_MAX_SIZE,
3612 &conn);
3613 if (!NT_STATUS_IS_OK(status)) {
3614 TALLOC_FREE(frame);
3615 return status;
3617 talloc_steal(frame, conn);
3619 ret = local_np_connect(
3620 pipe_name,
3621 NCALRPC,
3622 remote_client_name,
3623 remote_client_addr,
3624 local_server_name,
3625 local_server_addr,
3626 session_info,
3627 true,
3628 conn,
3629 &npa_stream);
3630 if (ret != 0) {
3631 DBG_DEBUG("local_np_connect for %s and "
3632 "user %s\\%s failed: %s\n",
3633 pipe_name,
3634 session_info->info->domain_name,
3635 session_info->info->account_name,
3636 strerror(ret));
3637 status = map_nt_error_from_unix(ret);
3638 TALLOC_FREE(frame);
3639 return status;
3642 status = rpc_transport_tstream_init(conn,
3643 &npa_stream,
3644 &conn->transport);
3645 if (!NT_STATUS_IS_OK(status)) {
3646 DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
3647 nt_errstr(status));
3648 TALLOC_FREE(frame);
3649 return status;
3651 conn->transport->transport = NCACN_NP;
3653 status = rpc_pipe_wrap_create(table,
3654 NULL,
3655 &assoc,
3656 &conn,
3657 mem_ctx,
3658 &result);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 TALLOC_FREE(frame);
3661 return status;
3663 talloc_steal(frame, result);
3665 status = rpccli_anon_bind_data(result, &auth);
3666 if (!NT_STATUS_IS_OK(status)) {
3667 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3668 nt_errstr(status));
3669 TALLOC_FREE(frame);
3670 return status;
3673 status = rpc_pipe_bind(result, auth);
3674 if (!NT_STATUS_IS_OK(status)) {
3675 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3676 TALLOC_FREE(frame);
3677 return status;
3680 *presult = talloc_move(mem_ctx, &result);
3681 TALLOC_FREE(frame);
3682 return NT_STATUS_OK;
3685 struct rpc_client_connection_np_state {
3686 struct cli_state *cli;
3687 const char *pipe_name;
3688 struct rpc_client_connection *conn;
3691 static void rpc_client_connection_np_done(struct tevent_req *subreq);
3693 static struct tevent_req *rpc_client_connection_np_send(
3694 TALLOC_CTX *mem_ctx,
3695 struct tevent_context *ev,
3696 struct cli_state *cli,
3697 const struct rpc_client_association *assoc)
3699 struct tevent_req *req = NULL, *subreq = NULL;
3700 struct rpc_client_connection_np_state *state = NULL;
3701 enum dcerpc_transport_t transport;
3702 const char *endpoint = NULL;
3703 struct smbXcli_session *session = NULL;
3704 NTSTATUS status;
3706 req = tevent_req_create(mem_ctx, &state,
3707 struct rpc_client_connection_np_state);
3708 if (req == NULL) {
3709 return NULL;
3712 transport = dcerpc_binding_get_transport(assoc->binding);
3713 if (transport != NCACN_NP) {
3714 tevent_req_nterror(req, NT_STATUS_RPC_WRONG_KIND_OF_BINDING);
3715 return tevent_req_post(req, ev);
3718 endpoint = dcerpc_binding_get_string_option(assoc->binding,
3719 "endpoint");
3720 if (endpoint == NULL) {
3721 tevent_req_nterror(req, NT_STATUS_RPC_INVALID_ENDPOINT_FORMAT);
3722 return tevent_req_post(req, ev);
3725 status = rpc_client_connection_create(state,
3726 assoc,
3727 TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE,
3728 &state->conn);
3729 if (tevent_req_nterror(req, status)) {
3730 return tevent_req_post(req, ev);
3733 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3734 session = cli->smb2.session;
3735 } else {
3736 session = cli->smb1.session;
3739 status = smbXcli_session_application_key(session, state->conn,
3740 &state->conn->transport_session_key);
3741 if (!NT_STATUS_IS_OK(status)) {
3742 state->conn->transport_session_key = data_blob_null;
3745 subreq = rpc_transport_np_init_send(state, ev, cli, endpoint);
3746 if (tevent_req_nomem(subreq, req)) {
3747 return tevent_req_post(req, ev);
3749 tevent_req_set_callback(subreq, rpc_client_connection_np_done, req);
3750 return req;
3753 static void rpc_client_connection_np_done(struct tevent_req *subreq)
3755 struct tevent_req *req = tevent_req_callback_data(
3756 subreq, struct tevent_req);
3757 struct rpc_client_connection_np_state *state = tevent_req_data(
3758 req, struct rpc_client_connection_np_state);
3759 NTSTATUS status;
3761 status = rpc_transport_np_init_recv(subreq,
3762 state->conn,
3763 &state->conn->transport);
3764 TALLOC_FREE(subreq);
3765 if (tevent_req_nterror(req, status)) {
3766 return;
3769 state->conn->transport->transport = NCACN_NP;
3771 tevent_req_done(req);
3774 static NTSTATUS rpc_client_connection_np_recv(
3775 struct tevent_req *req,
3776 TALLOC_CTX *mem_ctx,
3777 struct rpc_client_connection **pconn)
3779 struct rpc_client_connection_np_state *state = tevent_req_data(
3780 req, struct rpc_client_connection_np_state);
3781 NTSTATUS status;
3783 if (tevent_req_is_nterror(req, &status)) {
3784 tevent_req_received(req);
3785 return status;
3787 *pconn = talloc_move(mem_ctx, &state->conn);
3788 tevent_req_received(req);
3789 return NT_STATUS_OK;
3792 static NTSTATUS rpc_client_connection_np(struct cli_state *cli,
3793 const struct rpc_client_association *assoc,
3794 struct rpc_client_connection **pconn)
3796 struct tevent_context *ev = NULL;
3797 struct tevent_req *req = NULL;
3798 NTSTATUS status = NT_STATUS_NO_MEMORY;
3800 ev = samba_tevent_context_init(cli);
3801 if (ev == NULL) {
3802 goto fail;
3804 req = rpc_client_connection_np_send(ev, ev, cli, assoc);
3805 if (req == NULL) {
3806 goto fail;
3808 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3809 goto fail;
3811 status = rpc_client_connection_np_recv(req, NULL, pconn);
3812 fail:
3813 TALLOC_FREE(req);
3814 TALLOC_FREE(ev);
3815 return status;
3818 struct rpc_pipe_open_np_state {
3819 struct cli_state *cli;
3820 const struct ndr_interface_table *table;
3821 struct rpc_client_association *assoc;
3822 struct rpc_client_connection *conn;
3823 struct rpc_pipe_client *result;
3826 static void rpc_pipe_open_np_done(struct tevent_req *subreq);
3828 struct tevent_req *rpc_pipe_open_np_send(
3829 TALLOC_CTX *mem_ctx,
3830 struct tevent_context *ev,
3831 struct cli_state *cli,
3832 const struct ndr_interface_table *table)
3834 struct tevent_req *req = NULL, *subreq = NULL;
3835 struct rpc_pipe_open_np_state *state = NULL;
3836 const char *remote_name = NULL;
3837 const struct sockaddr_storage *remote_sockaddr = NULL;
3838 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3839 const char *pipe_name = NULL;
3840 NTSTATUS status;
3842 req = tevent_req_create(
3843 mem_ctx, &state, struct rpc_pipe_open_np_state);
3844 if (req == NULL) {
3845 return NULL;
3847 state->cli = cli;
3848 state->table = table;
3850 remote_name = smbXcli_conn_remote_name(cli->conn);
3851 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
3852 saddr.u.ss = *remote_sockaddr;
3854 pipe_name = dcerpc_default_transport_endpoint(state,
3855 NCACN_NP,
3856 table);
3857 if (tevent_req_nomem(pipe_name, req)) {
3858 return tevent_req_post(req, ev);
3861 status = rpc_client_association_create(state,
3862 default_bt_features,
3863 DCERPC_PROPOSE_HEADER_SIGNING,
3864 remote_name,
3865 NCACN_NP,
3866 &saddr,
3867 pipe_name,
3868 &state->assoc);
3869 if (tevent_req_nterror(req, status)) {
3870 return tevent_req_post(req, ev);
3873 subreq = rpc_client_connection_np_send(state, ev, cli, state->assoc);
3874 if (tevent_req_nomem(subreq, req)) {
3875 return tevent_req_post(req, ev);
3877 tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
3878 return req;
3881 static void rpc_pipe_open_np_done(struct tevent_req *subreq)
3883 struct tevent_req *req = tevent_req_callback_data(
3884 subreq, struct tevent_req);
3885 struct rpc_pipe_open_np_state *state = tevent_req_data(
3886 req, struct rpc_pipe_open_np_state);
3887 NTSTATUS status;
3889 status = rpc_client_connection_np_recv(subreq,
3890 state,
3891 &state->conn);
3892 TALLOC_FREE(subreq);
3893 if (tevent_req_nterror(req, status)) {
3894 return;
3897 status = rpc_pipe_wrap_create(state->table,
3898 state->cli,
3899 &state->assoc,
3900 &state->conn,
3901 state,
3902 &state->result);
3903 if (tevent_req_nterror(req, status)) {
3904 return;
3907 tevent_req_done(req);
3910 NTSTATUS rpc_pipe_open_np_recv(
3911 struct tevent_req *req,
3912 TALLOC_CTX *mem_ctx,
3913 struct rpc_pipe_client **_result)
3915 struct rpc_pipe_open_np_state *state = tevent_req_data(
3916 req, struct rpc_pipe_open_np_state);
3917 NTSTATUS status;
3919 if (tevent_req_is_nterror(req, &status)) {
3920 tevent_req_received(req);
3921 return status;
3923 *_result = talloc_move(mem_ctx, &state->result);
3924 tevent_req_received(req);
3925 return NT_STATUS_OK;
3928 /****************************************************************************
3929 Open a pipe to a remote server.
3930 ****************************************************************************/
3932 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3933 enum dcerpc_transport_t transport,
3934 const struct ndr_interface_table *table,
3935 const char *remote_name,
3936 const struct sockaddr_storage *remote_sockaddr,
3937 struct rpc_pipe_client **presult)
3939 TALLOC_CTX *frame = talloc_stackframe();
3940 struct samba_sockaddr saddr = { .sa_socklen = 0, };
3941 struct rpc_client_association *assoc = NULL;
3942 struct rpc_client_connection *conn = NULL;
3943 struct rpc_pipe_client *result = NULL;
3944 char _tcp_endpoint[6] = { 0, };
3945 const char *endpoint = NULL;
3946 NTSTATUS status;
3948 if (cli != NULL && remote_name == NULL) {
3949 remote_name = smbXcli_conn_remote_name(cli->conn);
3951 if (cli != NULL && remote_sockaddr == NULL) {
3952 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
3955 if (remote_sockaddr != NULL) {
3956 saddr.u.ss = *remote_sockaddr;
3957 } else {
3958 bool ok;
3960 ok = resolve_name(remote_name,
3961 &saddr.u.ss,
3962 NBT_NAME_SERVER,
3963 false);
3964 if (!ok) {
3965 TALLOC_FREE(frame);
3966 return NT_STATUS_NOT_FOUND;
3970 endpoint = dcerpc_default_transport_endpoint(frame,
3971 transport,
3972 table);
3973 if (endpoint == NULL) {
3974 uint16_t port = 0;
3976 if (transport != NCACN_IP_TCP) {
3977 TALLOC_FREE(frame);
3978 return NT_STATUS_RPC_NO_ENDPOINT_FOUND;
3981 status = rpc_pipe_get_tcp_port(remote_name,
3982 &saddr,
3983 table,
3984 &port);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 TALLOC_FREE(frame);
3987 return status;
3990 snprintf(_tcp_endpoint, sizeof(_tcp_endpoint), "%u", port);
3991 endpoint = _tcp_endpoint;
3994 status = rpc_client_association_create(NULL,
3995 default_bt_features,
3996 DCERPC_PROPOSE_HEADER_SIGNING,
3997 remote_name,
3998 transport,
3999 &saddr,
4000 endpoint,
4001 &assoc);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 TALLOC_FREE(frame);
4004 return status;
4006 talloc_steal(frame, assoc);
4008 switch (transport) {
4009 case NCACN_IP_TCP:
4010 status = rpc_pipe_open_tcp_port(NULL,
4011 assoc,
4012 &conn);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 TALLOC_FREE(frame);
4015 return status;
4017 talloc_steal(frame, conn);
4018 break;
4019 case NCACN_NP:
4020 status = rpc_client_connection_np(cli,
4021 assoc,
4022 &conn);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 TALLOC_FREE(frame);
4025 return status;
4027 talloc_steal(frame, conn);
4028 break;
4029 default:
4030 TALLOC_FREE(frame);
4031 return NT_STATUS_NOT_IMPLEMENTED;
4033 status = rpc_pipe_wrap_create(table,
4034 cli,
4035 &assoc,
4036 &conn,
4037 NULL,
4038 &result);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 TALLOC_FREE(frame);
4041 return status;
4044 *presult = result;
4045 TALLOC_FREE(frame);
4046 return NT_STATUS_OK;
4049 static NTSTATUS cli_rpc_pipe_client_reconnect(struct rpc_pipe_client *p)
4051 enum dcerpc_transport_t transport =
4052 dcerpc_binding_get_transport(p->assoc->binding);
4053 NTSTATUS status;
4055 switch (transport) {
4056 case NCACN_IP_TCP:
4057 status = rpc_pipe_open_tcp_port(p,
4058 p->assoc,
4059 &p->conn);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 return status;
4063 break;
4064 case NCACN_NP:
4065 status = rpc_client_connection_np(p->np_cli,
4066 p->assoc,
4067 &p->conn);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 return status;
4071 talloc_steal(p, p->conn);
4072 break;
4073 default:
4074 return NT_STATUS_NOT_IMPLEMENTED;
4077 return NT_STATUS_OK;
4080 NTSTATUS cli_rpc_pipe_client_prepare_alter(struct rpc_pipe_client *p,
4081 bool new_auth_context,
4082 const struct ndr_interface_table *table,
4083 bool new_pres_context)
4085 uint32_t f = p->assoc->features.negotiated;
4086 NTSTATUS status;
4088 if (!new_auth_context && !new_pres_context) {
4089 return NT_STATUS_INVALID_PARAMETER_MIX;
4092 TALLOC_FREE(p->binding_handle);
4094 if (new_auth_context) {
4095 p->auth = NULL;
4098 if (new_auth_context &&
4099 !(f & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING))
4102 * new auth context without
4103 * security context multiplexing.
4105 * We need to create a new transport
4106 * connection is the same association
4107 * group
4109 * We need to keep the old connection alive
4110 * in order to connect to the existing association
4111 * group..., so no TALLOC_FREE(p->conn)
4113 p->conn = NULL;
4114 status = cli_rpc_pipe_client_reconnect(p);
4115 if (!NT_STATUS_IS_OK(status)) {
4116 return status;
4120 if (new_pres_context) {
4121 /* rpc_pipe_bind_send should allocate an id... */
4122 p->pres_context_id = UINT16_MAX;
4123 p->table = table;
4124 p->transfer_syntax = ndr_transfer_syntax_ndr;
4127 return NT_STATUS_OK;
4130 /****************************************************************************
4131 Open a named pipe to an SMB server and bind anonymously.
4132 ****************************************************************************/
4134 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
4135 enum dcerpc_transport_t transport,
4136 const struct ndr_interface_table *table,
4137 const char *remote_name,
4138 const struct sockaddr_storage *remote_sockaddr,
4139 struct rpc_pipe_client **presult)
4141 struct rpc_pipe_client *result;
4142 struct pipe_auth_data *auth;
4143 NTSTATUS status;
4145 status = cli_rpc_pipe_open(cli,
4146 transport,
4147 table,
4148 remote_name,
4149 remote_sockaddr,
4150 &result);
4151 if (!NT_STATUS_IS_OK(status)) {
4152 return status;
4155 status = rpccli_anon_bind_data(result, &auth);
4156 if (!NT_STATUS_IS_OK(status)) {
4157 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
4158 nt_errstr(status)));
4159 TALLOC_FREE(result);
4160 return status;
4163 status = rpc_pipe_bind(result, auth);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 int lvl = 0;
4166 if (ndr_syntax_id_equal(&table->syntax_id,
4167 &ndr_table_dssetup.syntax_id)) {
4168 /* non AD domains just don't have this pipe, avoid
4169 * level 0 statement in that case - gd */
4170 lvl = 3;
4172 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
4173 "%s failed with error %s\n",
4174 table->name,
4175 nt_errstr(status) ));
4176 TALLOC_FREE(result);
4177 return status;
4180 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
4181 "%s and bound anonymously.\n",
4182 table->name,
4183 result->desthost));
4185 *presult = result;
4186 return NT_STATUS_OK;
4189 /****************************************************************************
4190 ****************************************************************************/
4192 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
4193 const struct ndr_interface_table *table,
4194 struct rpc_pipe_client **presult)
4196 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
4197 const struct sockaddr_storage *remote_sockaddr =
4198 smbXcli_conn_remote_sockaddr(cli->conn);
4200 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
4201 table,
4202 remote_name,
4203 remote_sockaddr,
4204 presult);
4207 /****************************************************************************
4208 Open a named pipe to an SMB server and bind using the mech specified
4210 This routine references the creds pointer that is passed in
4211 ****************************************************************************/
4213 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
4214 const struct ndr_interface_table *table,
4215 enum dcerpc_transport_t transport,
4216 enum dcerpc_AuthType auth_type,
4217 enum dcerpc_AuthLevel auth_level,
4218 const char *server,
4219 const struct sockaddr_storage *remote_sockaddr,
4220 struct cli_credentials *creds,
4221 struct rpc_pipe_client **presult)
4223 struct rpc_pipe_client *result;
4224 struct pipe_auth_data *auth = NULL;
4225 const char *target_service = table->authservices->names[0];
4226 NTSTATUS status;
4228 status = cli_rpc_pipe_open(cli,
4229 transport,
4230 table,
4231 server,
4232 remote_sockaddr,
4233 &result);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 return status;
4238 status = rpccli_generic_bind_data_from_creds(result,
4239 auth_type, auth_level,
4240 server, target_service,
4241 creds,
4242 &auth);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
4245 nt_errstr(status));
4246 goto err;
4249 status = rpc_pipe_bind(result, auth);
4250 if (!NT_STATUS_IS_OK(status)) {
4251 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
4252 nt_errstr(status));
4253 goto err;
4256 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
4257 table->name,
4258 result->desthost,
4259 cli_credentials_get_unparsed_name(creds, talloc_tos()));
4261 *presult = result;
4262 return NT_STATUS_OK;
4264 err:
4266 TALLOC_FREE(result);
4267 return status;
4270 NTSTATUS cli_rpc_pipe_client_auth_schannel(
4271 struct rpc_pipe_client *rpccli,
4272 const struct ndr_interface_table *table,
4273 struct netlogon_creds_cli_context *netlogon_creds)
4275 TALLOC_CTX *frame = talloc_stackframe();
4276 struct pipe_auth_data *rpcauth = NULL;
4277 const char *target_service = table->authservices->names[0];
4278 struct cli_credentials *cli_creds = NULL;
4279 enum dcerpc_AuthLevel auth_level;
4280 NTSTATUS status;
4282 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
4284 status = netlogon_creds_bind_cli_credentials(netlogon_creds,
4285 frame,
4286 &cli_creds);
4287 if (!NT_STATUS_IS_OK(status)) {
4288 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
4289 nt_errstr(status));
4290 TALLOC_FREE(frame);
4291 return status;
4294 status = rpccli_generic_bind_data_from_creds(rpccli,
4295 DCERPC_AUTH_TYPE_SCHANNEL,
4296 auth_level,
4297 rpccli->desthost,
4298 target_service,
4299 cli_creds,
4300 &rpcauth);
4301 if (!NT_STATUS_IS_OK(status)) {
4302 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
4303 nt_errstr(status)));
4304 TALLOC_FREE(frame);
4305 return status;
4308 status = rpc_pipe_bind(rpccli, rpcauth);
4309 if (!NT_STATUS_IS_OK(status)) {
4310 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
4311 nt_errstr(status));
4312 TALLOC_FREE(frame);
4313 return status;
4316 TALLOC_FREE(frame);
4317 return NT_STATUS_OK;
4320 NTSTATUS cli_rpc_pipe_open_bind_schannel(
4321 struct cli_state *cli,
4322 const struct ndr_interface_table *table,
4323 enum dcerpc_transport_t transport,
4324 struct netlogon_creds_cli_context *netlogon_creds,
4325 const char *remote_name,
4326 const struct sockaddr_storage *remote_sockaddr,
4327 struct rpc_pipe_client **_rpccli)
4329 struct rpc_pipe_client *rpccli = NULL;
4330 NTSTATUS status;
4332 status = cli_rpc_pipe_open(cli,
4333 transport,
4334 table,
4335 remote_name,
4336 remote_sockaddr,
4337 &rpccli);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 return status;
4342 status = cli_rpc_pipe_client_auth_schannel(rpccli,
4343 table,
4344 netlogon_creds);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
4347 nt_errstr(status));
4348 TALLOC_FREE(rpccli);
4349 return status;
4352 *_rpccli = rpccli;
4354 return NT_STATUS_OK;
4357 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
4358 const struct ndr_interface_table *table,
4359 enum dcerpc_transport_t transport,
4360 struct netlogon_creds_cli_context *netlogon_creds,
4361 const char *remote_name,
4362 const struct sockaddr_storage *remote_sockaddr,
4363 struct rpc_pipe_client **_rpccli)
4365 TALLOC_CTX *frame = talloc_stackframe();
4366 struct rpc_pipe_client *rpccli;
4367 struct netlogon_creds_cli_lck *lck;
4368 NTSTATUS status;
4370 status = netlogon_creds_cli_lck(
4371 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
4372 frame, &lck);
4373 if (!NT_STATUS_IS_OK(status)) {
4374 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
4375 nt_errstr(status));
4376 TALLOC_FREE(frame);
4377 return status;
4380 status = cli_rpc_pipe_open_bind_schannel(cli,
4381 table,
4382 transport,
4383 netlogon_creds,
4384 remote_name,
4385 remote_sockaddr,
4386 &rpccli);
4387 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
4388 netlogon_creds_cli_delete_lck(netlogon_creds);
4390 if (!NT_STATUS_IS_OK(status)) {
4391 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
4392 nt_errstr(status));
4393 TALLOC_FREE(frame);
4394 return status;
4397 if (ndr_syntax_id_equal(&table->syntax_id,
4398 &ndr_table_netlogon.syntax_id)) {
4399 status = netlogon_creds_cli_check(netlogon_creds,
4400 rpccli->binding_handle,
4401 NULL);
4402 if (!NT_STATUS_IS_OK(status)) {
4403 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
4404 nt_errstr(status)));
4405 TALLOC_FREE(frame);
4406 return status;
4410 DBG_DEBUG("opened pipe %s to machine %s with key %s "
4411 "and bound using schannel.\n",
4412 table->name, rpccli->desthost,
4413 netlogon_creds_cli_debug_string(netlogon_creds, lck));
4415 TALLOC_FREE(frame);
4417 *_rpccli = rpccli;
4418 return NT_STATUS_OK;