s3: Do not directly reference the ndr_table_* in rpcclient
[Samba/kamenim.git] / source3 / rpc_client / cli_pipe.c
blobbd7bf325c4c3c79b556041dda81388ce63a06267
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "../libcli/auth/libcli_auth.h"
22 #include "librpc/gen_ndr/cli_epmapper.h"
23 #include "../librpc/gen_ndr/ndr_schannel.h"
24 #include "../libcli/auth/schannel.h"
25 #include "../libcli/auth/schannel_proto.h"
26 #include "../libcli/auth/spnego.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_RPC_CLI
31 static const char *get_pipe_name_from_iface(
32 TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
34 int i;
35 const struct ndr_interface_string_array *ep = interface->endpoints;
36 char *p;
38 for (i=0; i<ep->count; i++) {
39 if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
40 break;
43 if (i == ep->count) {
44 return NULL;
48 * extract the pipe name without \\pipe from for example
49 * ncacn_np:[\\pipe\\epmapper]
51 p = strchr(ep->names[i]+15, ']');
52 if (p == NULL) {
53 return "PIPE";
55 return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
58 static const struct ndr_interface_table **interfaces;
60 bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
62 int num_interfaces = talloc_array_length(interfaces);
63 const struct ndr_interface_table **tmp;
64 int i;
66 for (i=0; i<num_interfaces; i++) {
67 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
68 &interface->syntax_id)) {
69 return true;
73 tmp = talloc_realloc(NULL, interfaces,
74 const struct ndr_interface_table *,
75 num_interfaces + 1);
76 if (tmp == NULL) {
77 DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
78 return false;
80 interfaces = tmp;
81 interfaces[num_interfaces] = interface;
82 return true;
85 static bool initialize_interfaces(void)
87 if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
88 return false;
90 if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
91 return false;
93 if (!smb_register_ndr_interface(&ndr_table_samr)) {
94 return false;
96 if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
97 return false;
99 if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
100 return false;
102 if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
103 return false;
105 if (!smb_register_ndr_interface(&ndr_table_winreg)) {
106 return false;
108 if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
109 return false;
111 if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
112 return false;
114 if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
115 return false;
117 if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
118 return false;
120 if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
121 return false;
123 if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
124 return false;
126 if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
127 return false;
129 if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
130 return false;
132 if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
133 return false;
135 return true;
138 const struct ndr_interface_table *get_iface_from_syntax(
139 const struct ndr_syntax_id *syntax)
141 int num_interfaces;
142 int i;
144 if (interfaces == NULL) {
145 if (!initialize_interfaces()) {
146 return NULL;
149 num_interfaces = talloc_array_length(interfaces);
151 for (i=0; i<num_interfaces; i++) {
152 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
153 return interfaces[i];
157 return NULL;
160 /****************************************************************************
161 Return the pipe name from the interface.
162 ****************************************************************************/
164 const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
165 const struct ndr_syntax_id *syntax)
167 const struct ndr_interface_table *interface;
168 char *guid_str;
169 const char *result;
171 interface = get_iface_from_syntax(syntax);
172 if (interface != NULL) {
173 result = get_pipe_name_from_iface(mem_ctx, interface);
174 if (result != NULL) {
175 return result;
180 * Here we should ask \\epmapper, but for now our code is only
181 * interested in the known pipes mentioned in pipe_names[]
184 guid_str = GUID_string(talloc_tos(), &syntax->uuid);
185 if (guid_str == NULL) {
186 return NULL;
188 result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
189 (int)syntax->if_version);
190 TALLOC_FREE(guid_str);
192 if (result == NULL) {
193 return "PIPE";
195 return result;
198 bool ndr_syntax_from_string(const char *s, uint32_t version,
199 struct ndr_syntax_id *syntax)
201 NTSTATUS status;
202 status = GUID_from_string(s, &syntax->uuid);
203 if (!NT_STATUS_IS_OK(status)) {
204 DEBUG(10, ("GUID_from_string returned %s\n",
205 nt_errstr(status)));
206 return false;
208 syntax->if_version = version;
209 return true;
212 /********************************************************************
213 Map internal value to wire value.
214 ********************************************************************/
216 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
218 switch (auth_type) {
220 case PIPE_AUTH_TYPE_NONE:
221 return DCERPC_AUTH_TYPE_NONE;
223 case PIPE_AUTH_TYPE_NTLMSSP:
224 return DCERPC_AUTH_TYPE_NTLMSSP;
226 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
227 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
228 return DCERPC_AUTH_TYPE_SPNEGO;
230 case PIPE_AUTH_TYPE_SCHANNEL:
231 return DCERPC_AUTH_TYPE_SCHANNEL;
233 case PIPE_AUTH_TYPE_KRB5:
234 return DCERPC_AUTH_TYPE_KRB5;
236 default:
237 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
238 "auth type %u\n",
239 (unsigned int)auth_type ));
240 break;
242 return -1;
245 /********************************************************************
246 Pipe description for a DEBUG
247 ********************************************************************/
248 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
249 struct rpc_pipe_client *cli)
251 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
252 if (result == NULL) {
253 return "pipe";
255 return result;
258 /********************************************************************
259 Rpc pipe call id.
260 ********************************************************************/
262 static uint32 get_rpc_call_id(void)
264 static uint32 call_id = 0;
265 return ++call_id;
269 * Realloc pdu to have a least "size" bytes
272 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
274 size_t extra_size;
276 if (prs_data_size(pdu) >= size) {
277 return true;
280 extra_size = size - prs_data_size(pdu);
282 if (!prs_force_grow(pdu, extra_size)) {
283 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
284 "%d bytes.\n", (int)extra_size));
285 return false;
288 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
289 (int)extra_size, prs_data_size(pdu)));
290 return true;
294 /*******************************************************************
295 Use SMBreadX to get rest of one fragment's worth of rpc data.
296 Reads the whole size or give an error message
297 ********************************************************************/
299 struct rpc_read_state {
300 struct event_context *ev;
301 struct rpc_cli_transport *transport;
302 uint8_t *data;
303 size_t size;
304 size_t num_read;
307 static void rpc_read_done(struct tevent_req *subreq);
309 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
310 struct event_context *ev,
311 struct rpc_cli_transport *transport,
312 uint8_t *data, size_t size)
314 struct tevent_req *req, *subreq;
315 struct rpc_read_state *state;
317 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
318 if (req == NULL) {
319 return NULL;
321 state->ev = ev;
322 state->transport = transport;
323 state->data = data;
324 state->size = size;
325 state->num_read = 0;
327 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
329 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
330 transport->priv);
331 if (subreq == NULL) {
332 goto fail;
334 tevent_req_set_callback(subreq, rpc_read_done, req);
335 return req;
337 fail:
338 TALLOC_FREE(req);
339 return NULL;
342 static void rpc_read_done(struct tevent_req *subreq)
344 struct tevent_req *req = tevent_req_callback_data(
345 subreq, struct tevent_req);
346 struct rpc_read_state *state = tevent_req_data(
347 req, struct rpc_read_state);
348 NTSTATUS status;
349 ssize_t received;
351 status = state->transport->read_recv(subreq, &received);
352 TALLOC_FREE(subreq);
353 if (!NT_STATUS_IS_OK(status)) {
354 tevent_req_nterror(req, status);
355 return;
358 state->num_read += received;
359 if (state->num_read == state->size) {
360 tevent_req_done(req);
361 return;
364 subreq = state->transport->read_send(state, state->ev,
365 state->data + state->num_read,
366 state->size - state->num_read,
367 state->transport->priv);
368 if (tevent_req_nomem(subreq, req)) {
369 return;
371 tevent_req_set_callback(subreq, rpc_read_done, req);
374 static NTSTATUS rpc_read_recv(struct tevent_req *req)
376 return tevent_req_simple_recv_ntstatus(req);
379 struct rpc_write_state {
380 struct event_context *ev;
381 struct rpc_cli_transport *transport;
382 const uint8_t *data;
383 size_t size;
384 size_t num_written;
387 static void rpc_write_done(struct tevent_req *subreq);
389 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
390 struct event_context *ev,
391 struct rpc_cli_transport *transport,
392 const uint8_t *data, size_t size)
394 struct tevent_req *req, *subreq;
395 struct rpc_write_state *state;
397 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
398 if (req == NULL) {
399 return NULL;
401 state->ev = ev;
402 state->transport = transport;
403 state->data = data;
404 state->size = size;
405 state->num_written = 0;
407 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
409 subreq = transport->write_send(state, ev, data, size, transport->priv);
410 if (subreq == NULL) {
411 goto fail;
413 tevent_req_set_callback(subreq, rpc_write_done, req);
414 return req;
415 fail:
416 TALLOC_FREE(req);
417 return NULL;
420 static void rpc_write_done(struct tevent_req *subreq)
422 struct tevent_req *req = tevent_req_callback_data(
423 subreq, struct tevent_req);
424 struct rpc_write_state *state = tevent_req_data(
425 req, struct rpc_write_state);
426 NTSTATUS status;
427 ssize_t written;
429 status = state->transport->write_recv(subreq, &written);
430 TALLOC_FREE(subreq);
431 if (!NT_STATUS_IS_OK(status)) {
432 tevent_req_nterror(req, status);
433 return;
436 state->num_written += written;
438 if (state->num_written == state->size) {
439 tevent_req_done(req);
440 return;
443 subreq = state->transport->write_send(state, state->ev,
444 state->data + state->num_written,
445 state->size - state->num_written,
446 state->transport->priv);
447 if (tevent_req_nomem(subreq, req)) {
448 return;
450 tevent_req_set_callback(subreq, rpc_write_done, req);
453 static NTSTATUS rpc_write_recv(struct tevent_req *req)
455 return tevent_req_simple_recv_ntstatus(req);
459 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
460 struct rpc_hdr_info *prhdr,
461 prs_struct *pdu)
464 * This next call sets the endian bit correctly in current_pdu. We
465 * will propagate this to rbuf later.
468 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, pdu, 0)) {
469 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
470 return NT_STATUS_BUFFER_TOO_SMALL;
473 if (prhdr->frag_len > cli->max_recv_frag) {
474 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
475 " we only allow %d\n", (int)prhdr->frag_len,
476 (int)cli->max_recv_frag));
477 return NT_STATUS_BUFFER_TOO_SMALL;
480 return NT_STATUS_OK;
483 /****************************************************************************
484 Try and get a PDU's worth of data from current_pdu. If not, then read more
485 from the wire.
486 ****************************************************************************/
488 struct get_complete_frag_state {
489 struct event_context *ev;
490 struct rpc_pipe_client *cli;
491 struct rpc_hdr_info *prhdr;
492 prs_struct *pdu;
495 static void get_complete_frag_got_header(struct tevent_req *subreq);
496 static void get_complete_frag_got_rest(struct tevent_req *subreq);
498 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
499 struct event_context *ev,
500 struct rpc_pipe_client *cli,
501 struct rpc_hdr_info *prhdr,
502 prs_struct *pdu)
504 struct tevent_req *req, *subreq;
505 struct get_complete_frag_state *state;
506 uint32_t pdu_len;
507 NTSTATUS status;
509 req = tevent_req_create(mem_ctx, &state,
510 struct get_complete_frag_state);
511 if (req == NULL) {
512 return NULL;
514 state->ev = ev;
515 state->cli = cli;
516 state->prhdr = prhdr;
517 state->pdu = pdu;
519 pdu_len = prs_data_size(pdu);
520 if (pdu_len < RPC_HEADER_LEN) {
521 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
522 status = NT_STATUS_NO_MEMORY;
523 goto post_status;
525 subreq = rpc_read_send(
526 state, state->ev,
527 state->cli->transport,
528 (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
529 RPC_HEADER_LEN - pdu_len);
530 if (subreq == NULL) {
531 status = NT_STATUS_NO_MEMORY;
532 goto post_status;
534 tevent_req_set_callback(subreq, get_complete_frag_got_header,
535 req);
536 return req;
539 status = parse_rpc_header(cli, prhdr, pdu);
540 if (!NT_STATUS_IS_OK(status)) {
541 goto post_status;
545 * Ensure we have frag_len bytes of data.
547 if (pdu_len < prhdr->frag_len) {
548 if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
549 status = NT_STATUS_NO_MEMORY;
550 goto post_status;
552 subreq = rpc_read_send(state, state->ev,
553 state->cli->transport,
554 (uint8_t *)(prs_data_p(pdu) + pdu_len),
555 prhdr->frag_len - pdu_len);
556 if (subreq == NULL) {
557 status = NT_STATUS_NO_MEMORY;
558 goto post_status;
560 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
561 req);
562 return req;
565 status = NT_STATUS_OK;
566 post_status:
567 if (NT_STATUS_IS_OK(status)) {
568 tevent_req_done(req);
569 } else {
570 tevent_req_nterror(req, status);
572 return tevent_req_post(req, ev);
575 static void get_complete_frag_got_header(struct tevent_req *subreq)
577 struct tevent_req *req = tevent_req_callback_data(
578 subreq, struct tevent_req);
579 struct get_complete_frag_state *state = tevent_req_data(
580 req, struct get_complete_frag_state);
581 NTSTATUS status;
583 status = rpc_read_recv(subreq);
584 TALLOC_FREE(subreq);
585 if (!NT_STATUS_IS_OK(status)) {
586 tevent_req_nterror(req, status);
587 return;
590 status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
591 if (!NT_STATUS_IS_OK(status)) {
592 tevent_req_nterror(req, status);
593 return;
596 if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
597 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
598 return;
602 * We're here in this piece of code because we've read exactly
603 * RPC_HEADER_LEN bytes into state->pdu.
606 subreq = rpc_read_send(
607 state, state->ev, state->cli->transport,
608 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
609 state->prhdr->frag_len - RPC_HEADER_LEN);
610 if (tevent_req_nomem(subreq, req)) {
611 return;
613 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
616 static void get_complete_frag_got_rest(struct tevent_req *subreq)
618 struct tevent_req *req = tevent_req_callback_data(
619 subreq, struct tevent_req);
620 NTSTATUS status;
622 status = rpc_read_recv(subreq);
623 TALLOC_FREE(subreq);
624 if (!NT_STATUS_IS_OK(status)) {
625 tevent_req_nterror(req, status);
626 return;
628 tevent_req_done(req);
631 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
633 return tevent_req_simple_recv_ntstatus(req);
636 /****************************************************************************
637 NTLMSSP specific sign/seal.
638 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
639 In fact I should probably abstract these into identical pieces of code... JRA.
640 ****************************************************************************/
642 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
643 prs_struct *current_pdu,
644 uint8 *p_ss_padding_len)
646 RPC_HDR_AUTH auth_info;
647 uint32 save_offset = prs_offset(current_pdu);
648 uint32 auth_len = prhdr->auth_len;
649 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
650 unsigned char *data = NULL;
651 size_t data_len;
652 unsigned char *full_packet_data = NULL;
653 size_t full_packet_data_len;
654 DATA_BLOB auth_blob;
655 NTSTATUS status;
657 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
658 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
659 return NT_STATUS_OK;
662 if (!ntlmssp_state) {
663 return NT_STATUS_INVALID_PARAMETER;
666 /* Ensure there's enough data for an authenticated response. */
667 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
668 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
669 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
670 (unsigned int)auth_len ));
671 return NT_STATUS_BUFFER_TOO_SMALL;
675 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
676 * after the RPC header.
677 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
678 * functions as NTLMv2 checks the rpc headers also.
681 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
682 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
684 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
685 full_packet_data_len = prhdr->frag_len - auth_len;
687 /* Pull the auth header and the following data into a blob. */
688 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
689 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
690 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
691 return NT_STATUS_BUFFER_TOO_SMALL;
694 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
695 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
696 return NT_STATUS_BUFFER_TOO_SMALL;
699 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
700 auth_blob.length = auth_len;
702 switch (cli->auth->auth_level) {
703 case DCERPC_AUTH_LEVEL_PRIVACY:
704 /* Data is encrypted. */
705 status = ntlmssp_unseal_packet(ntlmssp_state,
706 data, data_len,
707 full_packet_data,
708 full_packet_data_len,
709 &auth_blob);
710 if (!NT_STATUS_IS_OK(status)) {
711 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
712 "packet from %s. Error was %s.\n",
713 rpccli_pipe_txt(talloc_tos(), cli),
714 nt_errstr(status) ));
715 return status;
717 break;
718 case DCERPC_AUTH_LEVEL_INTEGRITY:
719 /* Data is signed. */
720 status = ntlmssp_check_packet(ntlmssp_state,
721 data, data_len,
722 full_packet_data,
723 full_packet_data_len,
724 &auth_blob);
725 if (!NT_STATUS_IS_OK(status)) {
726 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
727 "packet from %s. Error was %s.\n",
728 rpccli_pipe_txt(talloc_tos(), cli),
729 nt_errstr(status) ));
730 return status;
732 break;
733 default:
734 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
735 "auth level %d\n", cli->auth->auth_level));
736 return NT_STATUS_INVALID_INFO_CLASS;
740 * Return the current pointer to the data offset.
743 if(!prs_set_offset(current_pdu, save_offset)) {
744 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
745 (unsigned int)save_offset ));
746 return NT_STATUS_BUFFER_TOO_SMALL;
750 * Remember the padding length. We must remove it from the real data
751 * stream once the sign/seal is done.
754 *p_ss_padding_len = auth_info.auth_pad_len;
756 return NT_STATUS_OK;
759 /****************************************************************************
760 schannel specific sign/seal.
761 ****************************************************************************/
763 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
764 prs_struct *current_pdu,
765 uint8 *p_ss_padding_len)
767 RPC_HDR_AUTH auth_info;
768 uint32 auth_len = prhdr->auth_len;
769 uint32 save_offset = prs_offset(current_pdu);
770 struct schannel_state *schannel_auth =
771 cli->auth->a_u.schannel_auth;
772 uint8_t *data;
773 uint32 data_len;
774 DATA_BLOB blob;
775 NTSTATUS status;
777 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
778 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
779 return NT_STATUS_OK;
782 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
783 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
784 return NT_STATUS_INVALID_PARAMETER;
787 if (!schannel_auth) {
788 return NT_STATUS_INVALID_PARAMETER;
791 /* Ensure there's enough data for an authenticated response. */
792 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
793 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
794 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
795 (unsigned int)auth_len ));
796 return NT_STATUS_INVALID_PARAMETER;
799 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
801 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
802 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
803 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
804 return NT_STATUS_BUFFER_TOO_SMALL;
807 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
808 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
809 return NT_STATUS_BUFFER_TOO_SMALL;
812 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
813 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
814 auth_info.auth_type));
815 return NT_STATUS_BUFFER_TOO_SMALL;
818 blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), auth_len);
820 if (DEBUGLEVEL >= 10) {
821 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
824 data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
826 switch (cli->auth->auth_level) {
827 case DCERPC_AUTH_LEVEL_PRIVACY:
828 status = netsec_incoming_packet(schannel_auth,
829 talloc_tos(),
830 true,
831 data,
832 data_len,
833 &blob);
834 break;
835 case DCERPC_AUTH_LEVEL_INTEGRITY:
836 status = netsec_incoming_packet(schannel_auth,
837 talloc_tos(),
838 false,
839 data,
840 data_len,
841 &blob);
842 break;
843 default:
844 status = NT_STATUS_INTERNAL_ERROR;
845 break;
848 if (!NT_STATUS_IS_OK(status)) {
849 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
850 "Connection to %s (%s).\n",
851 rpccli_pipe_txt(talloc_tos(), cli),
852 nt_errstr(status)));
853 return NT_STATUS_INVALID_PARAMETER;
857 * Return the current pointer to the data offset.
860 if(!prs_set_offset(current_pdu, save_offset)) {
861 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
862 (unsigned int)save_offset ));
863 return NT_STATUS_BUFFER_TOO_SMALL;
867 * Remember the padding length. We must remove it from the real data
868 * stream once the sign/seal is done.
871 *p_ss_padding_len = auth_info.auth_pad_len;
873 return NT_STATUS_OK;
876 /****************************************************************************
877 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
878 ****************************************************************************/
880 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
881 prs_struct *current_pdu,
882 uint8 *p_ss_padding_len)
884 NTSTATUS ret = NT_STATUS_OK;
886 /* Paranioa checks for auth_len. */
887 if (prhdr->auth_len) {
888 if (prhdr->auth_len > prhdr->frag_len) {
889 return NT_STATUS_INVALID_PARAMETER;
892 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
893 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
894 /* Integer wrap attempt. */
895 return NT_STATUS_INVALID_PARAMETER;
900 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
903 switch(cli->auth->auth_type) {
904 case PIPE_AUTH_TYPE_NONE:
905 if (prhdr->auth_len) {
906 DEBUG(3, ("cli_pipe_validate_rpc_response: "
907 "Connection to %s - got non-zero "
908 "auth len %u.\n",
909 rpccli_pipe_txt(talloc_tos(), cli),
910 (unsigned int)prhdr->auth_len ));
911 return NT_STATUS_INVALID_PARAMETER;
913 break;
915 case PIPE_AUTH_TYPE_NTLMSSP:
916 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
917 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
918 if (!NT_STATUS_IS_OK(ret)) {
919 return ret;
921 break;
923 case PIPE_AUTH_TYPE_SCHANNEL:
924 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
925 if (!NT_STATUS_IS_OK(ret)) {
926 return ret;
928 break;
930 case PIPE_AUTH_TYPE_KRB5:
931 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
932 default:
933 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
934 "to %s - unknown internal auth type %u.\n",
935 rpccli_pipe_txt(talloc_tos(), cli),
936 cli->auth->auth_type ));
937 return NT_STATUS_INVALID_INFO_CLASS;
940 return NT_STATUS_OK;
943 /****************************************************************************
944 Do basic authentication checks on an incoming pdu.
945 ****************************************************************************/
947 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
948 prs_struct *current_pdu,
949 uint8 expected_pkt_type,
950 char **ppdata,
951 uint32 *pdata_len,
952 prs_struct *return_data)
955 NTSTATUS ret = NT_STATUS_OK;
956 uint32 current_pdu_len = prs_data_size(current_pdu);
958 if (current_pdu_len != prhdr->frag_len) {
959 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
960 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
961 return NT_STATUS_INVALID_PARAMETER;
965 * Point the return values at the real data including the RPC
966 * header. Just in case the caller wants it.
968 *ppdata = prs_data_p(current_pdu);
969 *pdata_len = current_pdu_len;
971 /* Ensure we have the correct type. */
972 switch (prhdr->pkt_type) {
973 case DCERPC_PKT_ALTER_RESP:
974 case DCERPC_PKT_BIND_ACK:
976 /* Alter context and bind ack share the same packet definitions. */
977 break;
980 case DCERPC_PKT_RESPONSE:
982 RPC_HDR_RESP rhdr_resp;
983 uint8 ss_padding_len = 0;
985 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
986 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
987 return NT_STATUS_BUFFER_TOO_SMALL;
990 /* Here's where we deal with incoming sign/seal. */
991 ret = cli_pipe_validate_rpc_response(cli, prhdr,
992 current_pdu, &ss_padding_len);
993 if (!NT_STATUS_IS_OK(ret)) {
994 return ret;
997 /* Point the return values at the NDR data. Remember to remove any ss padding. */
998 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1000 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
1001 return NT_STATUS_BUFFER_TOO_SMALL;
1004 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
1006 /* Remember to remove the auth footer. */
1007 if (prhdr->auth_len) {
1008 /* We've already done integer wrap tests on auth_len in
1009 cli_pipe_validate_rpc_response(). */
1010 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
1011 return NT_STATUS_BUFFER_TOO_SMALL;
1013 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
1016 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
1017 current_pdu_len, *pdata_len, ss_padding_len ));
1020 * If this is the first reply, and the allocation hint is reasonably, try and
1021 * set up the return_data parse_struct to the correct size.
1024 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
1025 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
1026 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
1027 "too large to allocate\n",
1028 (unsigned int)rhdr_resp.alloc_hint ));
1029 return NT_STATUS_NO_MEMORY;
1033 break;
1036 case DCERPC_PKT_BIND_NAK:
1037 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1038 "received from %s!\n",
1039 rpccli_pipe_txt(talloc_tos(), cli)));
1040 /* Use this for now... */
1041 return NT_STATUS_NETWORK_ACCESS_DENIED;
1043 case DCERPC_PKT_FAULT:
1045 RPC_HDR_RESP rhdr_resp;
1046 RPC_HDR_FAULT fault_resp;
1048 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1049 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1050 return NT_STATUS_BUFFER_TOO_SMALL;
1053 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
1054 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
1055 return NT_STATUS_BUFFER_TOO_SMALL;
1058 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1059 "code %s received from %s!\n",
1060 dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
1061 rpccli_pipe_txt(talloc_tos(), cli)));
1062 if (NT_STATUS_IS_OK(fault_resp.status)) {
1063 return NT_STATUS_UNSUCCESSFUL;
1064 } else {
1065 return fault_resp.status;
1069 default:
1070 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
1071 "from %s!\n",
1072 (unsigned int)prhdr->pkt_type,
1073 rpccli_pipe_txt(talloc_tos(), cli)));
1074 return NT_STATUS_INVALID_INFO_CLASS;
1077 if (prhdr->pkt_type != expected_pkt_type) {
1078 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1079 "got an unexpected RPC packet type - %u, not %u\n",
1080 rpccli_pipe_txt(talloc_tos(), cli),
1081 prhdr->pkt_type,
1082 expected_pkt_type));
1083 return NT_STATUS_INVALID_INFO_CLASS;
1086 /* Do this just before return - we don't want to modify any rpc header
1087 data before now as we may have needed to do cryptographic actions on
1088 it before. */
1090 if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) {
1091 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1092 "setting fragment first/last ON.\n"));
1093 prhdr->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST;
1096 return NT_STATUS_OK;
1099 /****************************************************************************
1100 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1101 Normally the frag_len and buffer size will match, but on the first trans
1102 reply there is a theoretical chance that buffer size > frag_len, so we must
1103 deal with that.
1104 ****************************************************************************/
1106 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
1108 uint32 current_pdu_len = prs_data_size(current_pdu);
1110 if (current_pdu_len < prhdr->frag_len) {
1111 return NT_STATUS_BUFFER_TOO_SMALL;
1114 /* Common case. */
1115 if (current_pdu_len == (uint32)prhdr->frag_len) {
1116 prs_mem_free(current_pdu);
1117 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1118 /* Make current_pdu dynamic with no memory. */
1119 prs_give_memory(current_pdu, 0, 0, True);
1120 return NT_STATUS_OK;
1124 * Oh no ! More data in buffer than we processed in current pdu.
1125 * Cheat. Move the data down and shrink the buffer.
1128 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1129 current_pdu_len - prhdr->frag_len);
1131 /* Remember to set the read offset back to zero. */
1132 prs_set_offset(current_pdu, 0);
1134 /* Shrink the buffer. */
1135 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1136 return NT_STATUS_BUFFER_TOO_SMALL;
1139 return NT_STATUS_OK;
1142 /****************************************************************************
1143 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1144 ****************************************************************************/
1146 struct cli_api_pipe_state {
1147 struct event_context *ev;
1148 struct rpc_cli_transport *transport;
1149 uint8_t *rdata;
1150 uint32_t rdata_len;
1153 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1154 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1155 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1157 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1158 struct event_context *ev,
1159 struct rpc_cli_transport *transport,
1160 uint8_t *data, size_t data_len,
1161 uint32_t max_rdata_len)
1163 struct tevent_req *req, *subreq;
1164 struct cli_api_pipe_state *state;
1165 NTSTATUS status;
1167 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1168 if (req == NULL) {
1169 return NULL;
1171 state->ev = ev;
1172 state->transport = transport;
1174 if (max_rdata_len < RPC_HEADER_LEN) {
1176 * For a RPC reply we always need at least RPC_HEADER_LEN
1177 * bytes. We check this here because we will receive
1178 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1180 status = NT_STATUS_INVALID_PARAMETER;
1181 goto post_status;
1184 if (transport->trans_send != NULL) {
1185 subreq = transport->trans_send(state, ev, data, data_len,
1186 max_rdata_len, transport->priv);
1187 if (subreq == NULL) {
1188 goto fail;
1190 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1191 return req;
1195 * If the transport does not provide a "trans" routine, i.e. for
1196 * example the ncacn_ip_tcp transport, do the write/read step here.
1199 subreq = rpc_write_send(state, ev, transport, data, data_len);
1200 if (subreq == NULL) {
1201 goto fail;
1203 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1204 return req;
1206 status = NT_STATUS_INVALID_PARAMETER;
1208 post_status:
1209 tevent_req_nterror(req, status);
1210 return tevent_req_post(req, ev);
1211 fail:
1212 TALLOC_FREE(req);
1213 return NULL;
1216 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1218 struct tevent_req *req = tevent_req_callback_data(
1219 subreq, struct tevent_req);
1220 struct cli_api_pipe_state *state = tevent_req_data(
1221 req, struct cli_api_pipe_state);
1222 NTSTATUS status;
1224 status = state->transport->trans_recv(subreq, state, &state->rdata,
1225 &state->rdata_len);
1226 TALLOC_FREE(subreq);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 tevent_req_nterror(req, status);
1229 return;
1231 tevent_req_done(req);
1234 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1236 struct tevent_req *req = tevent_req_callback_data(
1237 subreq, struct tevent_req);
1238 struct cli_api_pipe_state *state = tevent_req_data(
1239 req, struct cli_api_pipe_state);
1240 NTSTATUS status;
1242 status = rpc_write_recv(subreq);
1243 TALLOC_FREE(subreq);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 tevent_req_nterror(req, status);
1246 return;
1249 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1250 if (tevent_req_nomem(state->rdata, req)) {
1251 return;
1255 * We don't need to use rpc_read_send here, the upper layer will cope
1256 * with a short read, transport->trans_send could also return less
1257 * than state->max_rdata_len.
1259 subreq = state->transport->read_send(state, state->ev, state->rdata,
1260 RPC_HEADER_LEN,
1261 state->transport->priv);
1262 if (tevent_req_nomem(subreq, req)) {
1263 return;
1265 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1268 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1270 struct tevent_req *req = tevent_req_callback_data(
1271 subreq, struct tevent_req);
1272 struct cli_api_pipe_state *state = tevent_req_data(
1273 req, struct cli_api_pipe_state);
1274 NTSTATUS status;
1275 ssize_t received;
1277 status = state->transport->read_recv(subreq, &received);
1278 TALLOC_FREE(subreq);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 tevent_req_nterror(req, status);
1281 return;
1283 state->rdata_len = received;
1284 tevent_req_done(req);
1287 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1288 uint8_t **prdata, uint32_t *prdata_len)
1290 struct cli_api_pipe_state *state = tevent_req_data(
1291 req, struct cli_api_pipe_state);
1292 NTSTATUS status;
1294 if (tevent_req_is_nterror(req, &status)) {
1295 return status;
1298 *prdata = talloc_move(mem_ctx, &state->rdata);
1299 *prdata_len = state->rdata_len;
1300 return NT_STATUS_OK;
1303 /****************************************************************************
1304 Send data on an rpc pipe via trans. The prs_struct data must be the last
1305 pdu fragment of an NDR data stream.
1307 Receive response data from an rpc pipe, which may be large...
1309 Read the first fragment: unfortunately have to use SMBtrans for the first
1310 bit, then SMBreadX for subsequent bits.
1312 If first fragment received also wasn't the last fragment, continue
1313 getting fragments until we _do_ receive the last fragment.
1315 Request/Response PDU's look like the following...
1317 |<------------------PDU len----------------------------------------------->|
1318 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1320 +------------+-----------------+-------------+---------------+-------------+
1321 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1322 +------------+-----------------+-------------+---------------+-------------+
1324 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1325 signing & sealing being negotiated.
1327 ****************************************************************************/
1329 struct rpc_api_pipe_state {
1330 struct event_context *ev;
1331 struct rpc_pipe_client *cli;
1332 uint8_t expected_pkt_type;
1334 prs_struct incoming_frag;
1335 struct rpc_hdr_info rhdr;
1337 prs_struct incoming_pdu; /* Incoming reply */
1338 uint32_t incoming_pdu_offset;
1341 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1343 prs_mem_free(&state->incoming_frag);
1344 prs_mem_free(&state->incoming_pdu);
1345 return 0;
1348 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1349 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1351 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1352 struct event_context *ev,
1353 struct rpc_pipe_client *cli,
1354 prs_struct *data, /* Outgoing PDU */
1355 uint8_t expected_pkt_type)
1357 struct tevent_req *req, *subreq;
1358 struct rpc_api_pipe_state *state;
1359 uint16_t max_recv_frag;
1360 NTSTATUS status;
1362 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1363 if (req == NULL) {
1364 return NULL;
1366 state->ev = ev;
1367 state->cli = cli;
1368 state->expected_pkt_type = expected_pkt_type;
1369 state->incoming_pdu_offset = 0;
1371 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1373 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1374 /* Make incoming_pdu dynamic with no memory. */
1375 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1377 talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1380 * Ensure we're not sending too much.
1382 if (prs_offset(data) > cli->max_xmit_frag) {
1383 status = NT_STATUS_INVALID_PARAMETER;
1384 goto post_status;
1387 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1389 max_recv_frag = cli->max_recv_frag;
1391 #if 0
1392 max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1393 #endif
1395 subreq = cli_api_pipe_send(state, ev, cli->transport,
1396 (uint8_t *)prs_data_p(data),
1397 prs_offset(data), max_recv_frag);
1398 if (subreq == NULL) {
1399 goto fail;
1401 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1402 return req;
1404 post_status:
1405 tevent_req_nterror(req, status);
1406 return tevent_req_post(req, ev);
1407 fail:
1408 TALLOC_FREE(req);
1409 return NULL;
1412 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1414 struct tevent_req *req = tevent_req_callback_data(
1415 subreq, struct tevent_req);
1416 struct rpc_api_pipe_state *state = tevent_req_data(
1417 req, struct rpc_api_pipe_state);
1418 NTSTATUS status;
1419 uint8_t *rdata = NULL;
1420 uint32_t rdata_len = 0;
1421 char *rdata_copy;
1423 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1424 TALLOC_FREE(subreq);
1425 if (!NT_STATUS_IS_OK(status)) {
1426 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1427 tevent_req_nterror(req, status);
1428 return;
1431 if (rdata == NULL) {
1432 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1433 rpccli_pipe_txt(talloc_tos(), state->cli)));
1434 tevent_req_done(req);
1435 return;
1439 * Give the memory received from cli_trans as dynamic to the current
1440 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1441 * :-(
1443 rdata_copy = (char *)memdup(rdata, rdata_len);
1444 TALLOC_FREE(rdata);
1445 if (tevent_req_nomem(rdata_copy, req)) {
1446 return;
1448 prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
1450 /* Ensure we have enough data for a pdu. */
1451 subreq = get_complete_frag_send(state, state->ev, state->cli,
1452 &state->rhdr, &state->incoming_frag);
1453 if (tevent_req_nomem(subreq, req)) {
1454 return;
1456 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1459 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1461 struct tevent_req *req = tevent_req_callback_data(
1462 subreq, struct tevent_req);
1463 struct rpc_api_pipe_state *state = tevent_req_data(
1464 req, struct rpc_api_pipe_state);
1465 NTSTATUS status;
1466 char *rdata = NULL;
1467 uint32_t rdata_len = 0;
1469 status = get_complete_frag_recv(subreq);
1470 TALLOC_FREE(subreq);
1471 if (!NT_STATUS_IS_OK(status)) {
1472 DEBUG(5, ("get_complete_frag failed: %s\n",
1473 nt_errstr(status)));
1474 tevent_req_nterror(req, status);
1475 return;
1478 status = cli_pipe_validate_current_pdu(
1479 state->cli, &state->rhdr, &state->incoming_frag,
1480 state->expected_pkt_type, &rdata, &rdata_len,
1481 &state->incoming_pdu);
1483 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1484 (unsigned)prs_data_size(&state->incoming_frag),
1485 (unsigned)state->incoming_pdu_offset,
1486 nt_errstr(status)));
1488 if (!NT_STATUS_IS_OK(status)) {
1489 tevent_req_nterror(req, status);
1490 return;
1493 if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST)
1494 && (state->rhdr.pack_type[0] == 0)) {
1496 * Set the data type correctly for big-endian data on the
1497 * first packet.
1499 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1500 "big-endian.\n",
1501 rpccli_pipe_txt(talloc_tos(), state->cli)));
1502 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1505 * Check endianness on subsequent packets.
1507 if (state->incoming_frag.bigendian_data
1508 != state->incoming_pdu.bigendian_data) {
1509 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1510 "%s\n",
1511 state->incoming_pdu.bigendian_data?"big":"little",
1512 state->incoming_frag.bigendian_data?"big":"little"));
1513 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1514 return;
1517 /* Now copy the data portion out of the pdu into rbuf. */
1518 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1519 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1520 return;
1523 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1524 rdata, (size_t)rdata_len);
1525 state->incoming_pdu_offset += rdata_len;
1527 status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1528 &state->incoming_frag);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 tevent_req_nterror(req, status);
1531 return;
1534 if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
1535 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1536 rpccli_pipe_txt(talloc_tos(), state->cli),
1537 (unsigned)prs_data_size(&state->incoming_pdu)));
1538 tevent_req_done(req);
1539 return;
1542 subreq = get_complete_frag_send(state, state->ev, state->cli,
1543 &state->rhdr, &state->incoming_frag);
1544 if (tevent_req_nomem(subreq, req)) {
1545 return;
1547 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1550 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1551 prs_struct *reply_pdu)
1553 struct rpc_api_pipe_state *state = tevent_req_data(
1554 req, struct rpc_api_pipe_state);
1555 NTSTATUS status;
1557 if (tevent_req_is_nterror(req, &status)) {
1558 return status;
1561 *reply_pdu = state->incoming_pdu;
1562 reply_pdu->mem_ctx = mem_ctx;
1565 * Prevent state->incoming_pdu from being freed in
1566 * rpc_api_pipe_state_destructor()
1568 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1570 return NT_STATUS_OK;
1573 /*******************************************************************
1574 Creates krb5 auth bind.
1575 ********************************************************************/
1577 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1578 enum dcerpc_AuthLevel auth_level,
1579 RPC_HDR_AUTH *pauth_out,
1580 prs_struct *auth_data)
1582 #ifdef HAVE_KRB5
1583 int ret;
1584 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1585 DATA_BLOB tkt = data_blob_null;
1586 DATA_BLOB tkt_wrapped = data_blob_null;
1588 /* We may change the pad length before marshalling. */
1589 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
1591 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1592 a->service_principal ));
1594 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1596 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1597 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1599 if (ret) {
1600 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1601 "failed with %s\n",
1602 a->service_principal,
1603 error_message(ret) ));
1605 data_blob_free(&tkt);
1606 prs_mem_free(auth_data);
1607 return NT_STATUS_INVALID_PARAMETER;
1610 /* wrap that up in a nice GSS-API wrapping */
1611 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1613 data_blob_free(&tkt);
1615 /* Auth len in the rpc header doesn't include auth_header. */
1616 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1617 data_blob_free(&tkt_wrapped);
1618 prs_mem_free(auth_data);
1619 return NT_STATUS_NO_MEMORY;
1622 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1623 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1625 data_blob_free(&tkt_wrapped);
1626 return NT_STATUS_OK;
1627 #else
1628 return NT_STATUS_INVALID_PARAMETER;
1629 #endif
1632 /*******************************************************************
1633 Creates SPNEGO NTLMSSP auth bind.
1634 ********************************************************************/
1636 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1637 enum dcerpc_AuthLevel auth_level,
1638 RPC_HDR_AUTH *pauth_out,
1639 prs_struct *auth_data)
1641 NTSTATUS nt_status;
1642 DATA_BLOB null_blob = data_blob_null;
1643 DATA_BLOB request = data_blob_null;
1644 DATA_BLOB spnego_msg = data_blob_null;
1646 /* We may change the pad length before marshalling. */
1647 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
1649 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1650 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1651 null_blob,
1652 &request);
1654 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1655 data_blob_free(&request);
1656 prs_mem_free(auth_data);
1657 return nt_status;
1660 /* Wrap this in SPNEGO. */
1661 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1663 data_blob_free(&request);
1665 /* Auth len in the rpc header doesn't include auth_header. */
1666 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1667 data_blob_free(&spnego_msg);
1668 prs_mem_free(auth_data);
1669 return NT_STATUS_NO_MEMORY;
1672 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1673 dump_data(5, spnego_msg.data, spnego_msg.length);
1675 data_blob_free(&spnego_msg);
1676 return NT_STATUS_OK;
1679 /*******************************************************************
1680 Creates NTLMSSP auth bind.
1681 ********************************************************************/
1683 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1684 enum dcerpc_AuthLevel auth_level,
1685 RPC_HDR_AUTH *pauth_out,
1686 prs_struct *auth_data)
1688 NTSTATUS nt_status;
1689 DATA_BLOB null_blob = data_blob_null;
1690 DATA_BLOB request = data_blob_null;
1692 /* We may change the pad length before marshalling. */
1693 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
1695 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1696 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1697 null_blob,
1698 &request);
1700 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1701 data_blob_free(&request);
1702 prs_mem_free(auth_data);
1703 return nt_status;
1706 /* Auth len in the rpc header doesn't include auth_header. */
1707 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1708 data_blob_free(&request);
1709 prs_mem_free(auth_data);
1710 return NT_STATUS_NO_MEMORY;
1713 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1714 dump_data(5, request.data, request.length);
1716 data_blob_free(&request);
1717 return NT_STATUS_OK;
1720 /*******************************************************************
1721 Creates schannel auth bind.
1722 ********************************************************************/
1724 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1725 enum dcerpc_AuthLevel auth_level,
1726 RPC_HDR_AUTH *pauth_out,
1727 prs_struct *auth_data)
1729 struct NL_AUTH_MESSAGE r;
1730 enum ndr_err_code ndr_err;
1731 DATA_BLOB blob;
1733 /* We may change the pad length before marshalling. */
1734 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
1736 /* Use lp_workgroup() if domain not specified */
1738 if (!cli->auth->domain || !cli->auth->domain[0]) {
1739 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1740 if (cli->auth->domain == NULL) {
1741 return NT_STATUS_NO_MEMORY;
1746 * Now marshall the data into the auth parse_struct.
1749 r.MessageType = NL_NEGOTIATE_REQUEST;
1750 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1751 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1752 r.oem_netbios_domain.a = cli->auth->domain;
1753 r.oem_netbios_computer.a = global_myname();
1755 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &r,
1756 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
1757 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1758 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1759 prs_mem_free(auth_data);
1760 return ndr_map_error2ntstatus(ndr_err);
1763 if (DEBUGLEVEL >= 10) {
1764 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
1767 if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
1769 prs_mem_free(auth_data);
1770 return NT_STATUS_NO_MEMORY;
1773 return NT_STATUS_OK;
1776 /*******************************************************************
1777 Creates the internals of a DCE/RPC bind request or alter context PDU.
1778 ********************************************************************/
1780 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type,
1781 prs_struct *rpc_out,
1782 uint32 rpc_call_id,
1783 const struct ndr_syntax_id *abstract,
1784 const struct ndr_syntax_id *transfer,
1785 RPC_HDR_AUTH *phdr_auth,
1786 prs_struct *pauth_info)
1788 RPC_HDR hdr;
1789 RPC_HDR_RB hdr_rb;
1790 RPC_CONTEXT rpc_ctx;
1791 uint16 auth_len = prs_offset(pauth_info);
1792 uint8 ss_padding_len = 0;
1793 uint16 frag_len = 0;
1795 /* create the RPC context. */
1796 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1798 /* create the bind request RPC_HDR_RB */
1799 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1801 /* Start building the frag length. */
1802 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1804 /* Do we need to pad ? */
1805 if (auth_len) {
1806 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1807 if (data_len % 8) {
1808 ss_padding_len = 8 - (data_len % 8);
1809 phdr_auth->auth_pad_len = ss_padding_len;
1811 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1814 /* Create the request RPC_HDR */
1815 init_rpc_hdr(&hdr, pkt_type, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id, frag_len, auth_len);
1817 /* Marshall the RPC header */
1818 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1819 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1820 return NT_STATUS_NO_MEMORY;
1823 /* Marshall the bind request data */
1824 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1825 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1826 return NT_STATUS_NO_MEMORY;
1830 * Grow the outgoing buffer to store any auth info.
1833 if(auth_len != 0) {
1834 if (ss_padding_len) {
1835 char pad[8];
1836 memset(pad, '\0', 8);
1837 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1838 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1839 return NT_STATUS_NO_MEMORY;
1843 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1844 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1845 return NT_STATUS_NO_MEMORY;
1849 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1850 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1851 return NT_STATUS_NO_MEMORY;
1855 return NT_STATUS_OK;
1858 /*******************************************************************
1859 Creates a DCE/RPC bind request.
1860 ********************************************************************/
1862 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1863 prs_struct *rpc_out,
1864 uint32 rpc_call_id,
1865 const struct ndr_syntax_id *abstract,
1866 const struct ndr_syntax_id *transfer,
1867 enum pipe_auth_type auth_type,
1868 enum dcerpc_AuthLevel auth_level)
1870 RPC_HDR_AUTH hdr_auth;
1871 prs_struct auth_info;
1872 NTSTATUS ret = NT_STATUS_OK;
1874 ZERO_STRUCT(hdr_auth);
1875 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1876 return NT_STATUS_NO_MEMORY;
1878 switch (auth_type) {
1879 case PIPE_AUTH_TYPE_SCHANNEL:
1880 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1881 if (!NT_STATUS_IS_OK(ret)) {
1882 prs_mem_free(&auth_info);
1883 return ret;
1885 break;
1887 case PIPE_AUTH_TYPE_NTLMSSP:
1888 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1889 if (!NT_STATUS_IS_OK(ret)) {
1890 prs_mem_free(&auth_info);
1891 return ret;
1893 break;
1895 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1896 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1897 if (!NT_STATUS_IS_OK(ret)) {
1898 prs_mem_free(&auth_info);
1899 return ret;
1901 break;
1903 case PIPE_AUTH_TYPE_KRB5:
1904 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1905 if (!NT_STATUS_IS_OK(ret)) {
1906 prs_mem_free(&auth_info);
1907 return ret;
1909 break;
1911 case PIPE_AUTH_TYPE_NONE:
1912 break;
1914 default:
1915 /* "Can't" happen. */
1916 return NT_STATUS_INVALID_INFO_CLASS;
1919 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1920 rpc_out,
1921 rpc_call_id,
1922 abstract,
1923 transfer,
1924 &hdr_auth,
1925 &auth_info);
1927 prs_mem_free(&auth_info);
1928 return ret;
1931 /*******************************************************************
1932 Create and add the NTLMSSP sign/seal auth header and data.
1933 ********************************************************************/
1935 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1936 RPC_HDR *phdr,
1937 uint32 ss_padding_len,
1938 prs_struct *outgoing_pdu)
1940 RPC_HDR_AUTH auth_info;
1941 NTSTATUS status;
1942 DATA_BLOB auth_blob = data_blob_null;
1943 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1945 if (!cli->auth->a_u.ntlmssp_state) {
1946 return NT_STATUS_INVALID_PARAMETER;
1949 /* Init and marshall the auth header. */
1950 init_rpc_hdr_auth(&auth_info,
1951 map_pipe_auth_type_to_rpc_auth_type(
1952 cli->auth->auth_type),
1953 cli->auth->auth_level,
1954 ss_padding_len,
1955 1 /* context id. */);
1957 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1958 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1959 data_blob_free(&auth_blob);
1960 return NT_STATUS_NO_MEMORY;
1963 switch (cli->auth->auth_level) {
1964 case DCERPC_AUTH_LEVEL_PRIVACY:
1965 /* Data portion is encrypted. */
1966 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1967 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1968 data_and_pad_len,
1969 (unsigned char *)prs_data_p(outgoing_pdu),
1970 (size_t)prs_offset(outgoing_pdu),
1971 &auth_blob);
1972 if (!NT_STATUS_IS_OK(status)) {
1973 data_blob_free(&auth_blob);
1974 return status;
1976 break;
1978 case DCERPC_AUTH_LEVEL_INTEGRITY:
1979 /* Data is signed. */
1980 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1981 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1982 data_and_pad_len,
1983 (unsigned char *)prs_data_p(outgoing_pdu),
1984 (size_t)prs_offset(outgoing_pdu),
1985 &auth_blob);
1986 if (!NT_STATUS_IS_OK(status)) {
1987 data_blob_free(&auth_blob);
1988 return status;
1990 break;
1992 default:
1993 /* Can't happen. */
1994 smb_panic("bad auth level");
1995 /* Notreached. */
1996 return NT_STATUS_INVALID_PARAMETER;
1999 /* Finally marshall the blob. */
2001 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
2002 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
2003 (unsigned int)NTLMSSP_SIG_SIZE));
2004 data_blob_free(&auth_blob);
2005 return NT_STATUS_NO_MEMORY;
2008 data_blob_free(&auth_blob);
2009 return NT_STATUS_OK;
2012 /*******************************************************************
2013 Create and add the schannel sign/seal auth header and data.
2014 ********************************************************************/
2016 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2017 RPC_HDR *phdr,
2018 uint32 ss_padding_len,
2019 prs_struct *outgoing_pdu)
2021 RPC_HDR_AUTH auth_info;
2022 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2023 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2024 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2025 DATA_BLOB blob;
2026 NTSTATUS status;
2028 if (!sas) {
2029 return NT_STATUS_INVALID_PARAMETER;
2032 /* Init and marshall the auth header. */
2033 init_rpc_hdr_auth(&auth_info,
2034 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2035 cli->auth->auth_level,
2036 ss_padding_len,
2037 1 /* context id. */);
2039 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
2040 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
2041 return NT_STATUS_NO_MEMORY;
2044 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2045 sas->seq_num));
2047 switch (cli->auth->auth_level) {
2048 case DCERPC_AUTH_LEVEL_PRIVACY:
2049 status = netsec_outgoing_packet(sas,
2050 talloc_tos(),
2051 true,
2052 (uint8_t *)data_p,
2053 data_and_pad_len,
2054 &blob);
2055 break;
2056 case DCERPC_AUTH_LEVEL_INTEGRITY:
2057 status = netsec_outgoing_packet(sas,
2058 talloc_tos(),
2059 false,
2060 (uint8_t *)data_p,
2061 data_and_pad_len,
2062 &blob);
2063 break;
2064 default:
2065 status = NT_STATUS_INTERNAL_ERROR;
2066 break;
2069 if (!NT_STATUS_IS_OK(status)) {
2070 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2071 nt_errstr(status)));
2072 return status;
2075 if (DEBUGLEVEL >= 10) {
2076 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2079 /* Finally marshall the blob. */
2080 if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
2081 return NT_STATUS_NO_MEMORY;
2084 return NT_STATUS_OK;
2087 /*******************************************************************
2088 Calculate how much data we're going to send in this packet, also
2089 work out any sign/seal padding length.
2090 ********************************************************************/
2092 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2093 uint32 data_left,
2094 uint16 *p_frag_len,
2095 uint16 *p_auth_len,
2096 uint32 *p_ss_padding)
2098 uint32 data_space, data_len;
2100 #if 0
2101 if ((data_left > 0) && (sys_random() % 2)) {
2102 data_left = MAX(data_left/2, 1);
2104 #endif
2106 switch (cli->auth->auth_level) {
2107 case DCERPC_AUTH_LEVEL_NONE:
2108 case DCERPC_AUTH_LEVEL_CONNECT:
2109 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2110 data_len = MIN(data_space, data_left);
2111 *p_ss_padding = 0;
2112 *p_auth_len = 0;
2113 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2114 return data_len;
2116 case DCERPC_AUTH_LEVEL_INTEGRITY:
2117 case DCERPC_AUTH_LEVEL_PRIVACY:
2118 /* Treat the same for all authenticated rpc requests. */
2119 switch(cli->auth->auth_type) {
2120 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2121 case PIPE_AUTH_TYPE_NTLMSSP:
2122 *p_auth_len = NTLMSSP_SIG_SIZE;
2123 break;
2124 case PIPE_AUTH_TYPE_SCHANNEL:
2125 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2126 break;
2127 default:
2128 smb_panic("bad auth type");
2129 break;
2132 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2133 RPC_HDR_AUTH_LEN - *p_auth_len;
2135 data_len = MIN(data_space, data_left);
2136 *p_ss_padding = 0;
2137 if (data_len % 8) {
2138 *p_ss_padding = 8 - (data_len % 8);
2140 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
2141 data_len + *p_ss_padding + /* data plus padding. */
2142 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
2143 return data_len;
2145 default:
2146 smb_panic("bad auth level");
2147 /* Notreached. */
2148 return 0;
2152 /*******************************************************************
2153 External interface.
2154 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2155 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2156 and deals with signing/sealing details.
2157 ********************************************************************/
2159 struct rpc_api_pipe_req_state {
2160 struct event_context *ev;
2161 struct rpc_pipe_client *cli;
2162 uint8_t op_num;
2163 uint32_t call_id;
2164 prs_struct *req_data;
2165 uint32_t req_data_sent;
2166 prs_struct outgoing_frag;
2167 prs_struct reply_pdu;
2170 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2172 prs_mem_free(&s->outgoing_frag);
2173 prs_mem_free(&s->reply_pdu);
2174 return 0;
2177 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2178 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2179 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2180 bool *is_last_frag);
2182 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2183 struct event_context *ev,
2184 struct rpc_pipe_client *cli,
2185 uint8_t op_num,
2186 prs_struct *req_data)
2188 struct tevent_req *req, *subreq;
2189 struct rpc_api_pipe_req_state *state;
2190 NTSTATUS status;
2191 bool is_last_frag;
2193 req = tevent_req_create(mem_ctx, &state,
2194 struct rpc_api_pipe_req_state);
2195 if (req == NULL) {
2196 return NULL;
2198 state->ev = ev;
2199 state->cli = cli;
2200 state->op_num = op_num;
2201 state->req_data = req_data;
2202 state->req_data_sent = 0;
2203 state->call_id = get_rpc_call_id();
2205 if (cli->max_xmit_frag
2206 < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2207 /* Server is screwed up ! */
2208 status = NT_STATUS_INVALID_PARAMETER;
2209 goto post_status;
2212 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2214 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2215 state, MARSHALL)) {
2216 goto fail;
2219 talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2221 status = prepare_next_frag(state, &is_last_frag);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 goto post_status;
2226 if (is_last_frag) {
2227 subreq = rpc_api_pipe_send(state, ev, state->cli,
2228 &state->outgoing_frag,
2229 DCERPC_PKT_RESPONSE);
2230 if (subreq == NULL) {
2231 goto fail;
2233 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2234 } else {
2235 subreq = rpc_write_send(
2236 state, ev, cli->transport,
2237 (uint8_t *)prs_data_p(&state->outgoing_frag),
2238 prs_offset(&state->outgoing_frag));
2239 if (subreq == NULL) {
2240 goto fail;
2242 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2243 req);
2245 return req;
2247 post_status:
2248 tevent_req_nterror(req, status);
2249 return tevent_req_post(req, ev);
2250 fail:
2251 TALLOC_FREE(req);
2252 return NULL;
2255 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2256 bool *is_last_frag)
2258 RPC_HDR hdr;
2259 RPC_HDR_REQ hdr_req;
2260 uint32_t data_sent_thistime;
2261 uint16_t auth_len;
2262 uint16_t frag_len;
2263 uint8_t flags = 0;
2264 uint32_t ss_padding;
2265 uint32_t data_left;
2266 char pad[8] = { 0, };
2267 NTSTATUS status;
2269 data_left = prs_offset(state->req_data) - state->req_data_sent;
2271 data_sent_thistime = calculate_data_len_tosend(
2272 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2274 if (state->req_data_sent == 0) {
2275 flags = DCERPC_PFC_FLAG_FIRST;
2278 if (data_sent_thistime == data_left) {
2279 flags |= DCERPC_PFC_FLAG_LAST;
2282 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2283 return NT_STATUS_NO_MEMORY;
2286 /* Create and marshall the header and request header. */
2287 init_rpc_hdr(&hdr, DCERPC_PKT_REQUEST, flags, state->call_id, frag_len,
2288 auth_len);
2290 if (!smb_io_rpc_hdr("hdr ", &hdr, &state->outgoing_frag, 0)) {
2291 return NT_STATUS_NO_MEMORY;
2294 /* Create the rpc request RPC_HDR_REQ */
2295 init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2296 state->op_num);
2298 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2299 &state->outgoing_frag, 0)) {
2300 return NT_STATUS_NO_MEMORY;
2303 /* Copy in the data, plus any ss padding. */
2304 if (!prs_append_some_prs_data(&state->outgoing_frag,
2305 state->req_data, state->req_data_sent,
2306 data_sent_thistime)) {
2307 return NT_STATUS_NO_MEMORY;
2310 /* Copy the sign/seal padding data. */
2311 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2312 return NT_STATUS_NO_MEMORY;
2315 /* Generate any auth sign/seal and add the auth footer. */
2316 switch (state->cli->auth->auth_type) {
2317 case PIPE_AUTH_TYPE_NONE:
2318 status = NT_STATUS_OK;
2319 break;
2320 case PIPE_AUTH_TYPE_NTLMSSP:
2321 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2322 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2323 &state->outgoing_frag);
2324 break;
2325 case PIPE_AUTH_TYPE_SCHANNEL:
2326 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2327 &state->outgoing_frag);
2328 break;
2329 default:
2330 status = NT_STATUS_INVALID_PARAMETER;
2331 break;
2334 state->req_data_sent += data_sent_thistime;
2335 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2337 return status;
2340 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2342 struct tevent_req *req = tevent_req_callback_data(
2343 subreq, struct tevent_req);
2344 struct rpc_api_pipe_req_state *state = tevent_req_data(
2345 req, struct rpc_api_pipe_req_state);
2346 NTSTATUS status;
2347 bool is_last_frag;
2349 status = rpc_write_recv(subreq);
2350 TALLOC_FREE(subreq);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 tevent_req_nterror(req, status);
2353 return;
2356 status = prepare_next_frag(state, &is_last_frag);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 tevent_req_nterror(req, status);
2359 return;
2362 if (is_last_frag) {
2363 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2364 &state->outgoing_frag,
2365 DCERPC_PKT_RESPONSE);
2366 if (tevent_req_nomem(subreq, req)) {
2367 return;
2369 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2370 } else {
2371 subreq = rpc_write_send(
2372 state, state->ev,
2373 state->cli->transport,
2374 (uint8_t *)prs_data_p(&state->outgoing_frag),
2375 prs_offset(&state->outgoing_frag));
2376 if (tevent_req_nomem(subreq, req)) {
2377 return;
2379 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2380 req);
2384 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2386 struct tevent_req *req = tevent_req_callback_data(
2387 subreq, struct tevent_req);
2388 struct rpc_api_pipe_req_state *state = tevent_req_data(
2389 req, struct rpc_api_pipe_req_state);
2390 NTSTATUS status;
2392 status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2393 TALLOC_FREE(subreq);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 tevent_req_nterror(req, status);
2396 return;
2398 tevent_req_done(req);
2401 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2402 prs_struct *reply_pdu)
2404 struct rpc_api_pipe_req_state *state = tevent_req_data(
2405 req, struct rpc_api_pipe_req_state);
2406 NTSTATUS status;
2408 if (tevent_req_is_nterror(req, &status)) {
2410 * We always have to initialize to reply pdu, even if there is
2411 * none. The rpccli_* caller routines expect this.
2413 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2414 return status;
2417 *reply_pdu = state->reply_pdu;
2418 reply_pdu->mem_ctx = mem_ctx;
2421 * Prevent state->req_pdu from being freed in
2422 * rpc_api_pipe_req_state_destructor()
2424 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2426 return NT_STATUS_OK;
2429 #if 0
2430 /****************************************************************************
2431 Set the handle state.
2432 ****************************************************************************/
2434 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2435 const char *pipe_name, uint16 device_state)
2437 bool state_set = False;
2438 char param[2];
2439 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2440 char *rparam = NULL;
2441 char *rdata = NULL;
2442 uint32 rparam_len, rdata_len;
2444 if (pipe_name == NULL)
2445 return False;
2447 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2448 cli->fnum, pipe_name, device_state));
2450 /* create parameters: device state */
2451 SSVAL(param, 0, device_state);
2453 /* create setup parameters. */
2454 setup[0] = 0x0001;
2455 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2457 /* send the data on \PIPE\ */
2458 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2459 setup, 2, 0, /* setup, length, max */
2460 param, 2, 0, /* param, length, max */
2461 NULL, 0, 1024, /* data, length, max */
2462 &rparam, &rparam_len, /* return param, length */
2463 &rdata, &rdata_len)) /* return data, length */
2465 DEBUG(5, ("Set Handle state: return OK\n"));
2466 state_set = True;
2469 SAFE_FREE(rparam);
2470 SAFE_FREE(rdata);
2472 return state_set;
2474 #endif
2476 /****************************************************************************
2477 Check the rpc bind acknowledge response.
2478 ****************************************************************************/
2480 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2481 const struct ndr_syntax_id *transfer)
2483 if ( hdr_ba->addr.len == 0) {
2484 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2487 /* check the transfer syntax */
2488 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2489 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2490 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2491 return False;
2494 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2495 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2496 hdr_ba->res.num_results, hdr_ba->res.reason));
2499 DEBUG(5,("check_bind_response: accepted!\n"));
2500 return True;
2503 /*******************************************************************
2504 Creates a DCE/RPC bind authentication response.
2505 This is the packet that is sent back to the server once we
2506 have received a BIND-ACK, to finish the third leg of
2507 the authentication handshake.
2508 ********************************************************************/
2510 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2511 uint32 rpc_call_id,
2512 enum pipe_auth_type auth_type,
2513 enum dcerpc_AuthLevel auth_level,
2514 DATA_BLOB *pauth_blob,
2515 prs_struct *rpc_out)
2517 RPC_HDR hdr;
2518 RPC_HDR_AUTH hdr_auth;
2519 uint32 pad = 0;
2521 /* Create the request RPC_HDR */
2522 init_rpc_hdr(&hdr, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id,
2523 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2524 pauth_blob->length );
2526 /* Marshall it. */
2527 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2528 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2529 return NT_STATUS_NO_MEMORY;
2533 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2534 about padding - shouldn't this pad to length 8 ? JRA.
2537 /* 4 bytes padding. */
2538 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2539 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2540 return NT_STATUS_NO_MEMORY;
2543 /* Create the request RPC_HDR_AUTHA */
2544 init_rpc_hdr_auth(&hdr_auth,
2545 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2546 auth_level, 0, 1);
2548 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2549 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2550 return NT_STATUS_NO_MEMORY;
2554 * Append the auth data to the outgoing buffer.
2557 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2558 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2559 return NT_STATUS_NO_MEMORY;
2562 return NT_STATUS_OK;
2565 /*******************************************************************
2566 Creates a DCE/RPC bind alter context authentication request which
2567 may contain a spnego auth blobl
2568 ********************************************************************/
2570 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2571 const struct ndr_syntax_id *abstract,
2572 const struct ndr_syntax_id *transfer,
2573 enum dcerpc_AuthLevel auth_level,
2574 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2575 prs_struct *rpc_out)
2577 RPC_HDR_AUTH hdr_auth;
2578 prs_struct auth_info;
2579 NTSTATUS ret = NT_STATUS_OK;
2581 ZERO_STRUCT(hdr_auth);
2582 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2583 return NT_STATUS_NO_MEMORY;
2585 /* We may change the pad length before marshalling. */
2586 init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
2588 if (pauth_blob->length) {
2589 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2590 prs_mem_free(&auth_info);
2591 return NT_STATUS_NO_MEMORY;
2595 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2596 rpc_out,
2597 rpc_call_id,
2598 abstract,
2599 transfer,
2600 &hdr_auth,
2601 &auth_info);
2602 prs_mem_free(&auth_info);
2603 return ret;
2606 /****************************************************************************
2607 Do an rpc bind.
2608 ****************************************************************************/
2610 struct rpc_pipe_bind_state {
2611 struct event_context *ev;
2612 struct rpc_pipe_client *cli;
2613 prs_struct rpc_out;
2614 uint32_t rpc_call_id;
2617 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2619 prs_mem_free(&state->rpc_out);
2620 return 0;
2623 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2624 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2625 struct rpc_pipe_bind_state *state,
2626 struct rpc_hdr_info *phdr,
2627 prs_struct *reply_pdu);
2628 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2629 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2630 struct rpc_pipe_bind_state *state,
2631 struct rpc_hdr_info *phdr,
2632 prs_struct *reply_pdu);
2633 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2635 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2636 struct event_context *ev,
2637 struct rpc_pipe_client *cli,
2638 struct cli_pipe_auth_data *auth)
2640 struct tevent_req *req, *subreq;
2641 struct rpc_pipe_bind_state *state;
2642 NTSTATUS status;
2644 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2645 if (req == NULL) {
2646 return NULL;
2649 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2650 rpccli_pipe_txt(talloc_tos(), cli),
2651 (unsigned int)auth->auth_type,
2652 (unsigned int)auth->auth_level ));
2654 state->ev = ev;
2655 state->cli = cli;
2656 state->rpc_call_id = get_rpc_call_id();
2658 prs_init_empty(&state->rpc_out, state, MARSHALL);
2659 talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2661 cli->auth = talloc_move(cli, &auth);
2663 /* Marshall the outgoing data. */
2664 status = create_rpc_bind_req(cli, &state->rpc_out,
2665 state->rpc_call_id,
2666 &cli->abstract_syntax,
2667 &cli->transfer_syntax,
2668 cli->auth->auth_type,
2669 cli->auth->auth_level);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 goto post_status;
2675 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2676 DCERPC_PKT_BIND_ACK);
2677 if (subreq == NULL) {
2678 goto fail;
2680 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2681 return req;
2683 post_status:
2684 tevent_req_nterror(req, status);
2685 return tevent_req_post(req, ev);
2686 fail:
2687 TALLOC_FREE(req);
2688 return NULL;
2691 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2693 struct tevent_req *req = tevent_req_callback_data(
2694 subreq, struct tevent_req);
2695 struct rpc_pipe_bind_state *state = tevent_req_data(
2696 req, struct rpc_pipe_bind_state);
2697 prs_struct reply_pdu;
2698 struct rpc_hdr_info hdr;
2699 struct rpc_hdr_ba_info hdr_ba;
2700 NTSTATUS status;
2702 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2703 TALLOC_FREE(subreq);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2706 rpccli_pipe_txt(talloc_tos(), state->cli),
2707 nt_errstr(status)));
2708 tevent_req_nterror(req, status);
2709 return;
2712 /* Unmarshall the RPC header */
2713 if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2714 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2715 prs_mem_free(&reply_pdu);
2716 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2717 return;
2720 if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2721 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2722 "RPC_HDR_BA.\n"));
2723 prs_mem_free(&reply_pdu);
2724 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2725 return;
2728 if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2729 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2730 prs_mem_free(&reply_pdu);
2731 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2732 return;
2735 state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2736 state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2739 * For authenticated binds we may need to do 3 or 4 leg binds.
2742 switch(state->cli->auth->auth_type) {
2744 case PIPE_AUTH_TYPE_NONE:
2745 case PIPE_AUTH_TYPE_SCHANNEL:
2746 /* Bind complete. */
2747 prs_mem_free(&reply_pdu);
2748 tevent_req_done(req);
2749 break;
2751 case PIPE_AUTH_TYPE_NTLMSSP:
2752 /* Need to send AUTH3 packet - no reply. */
2753 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2754 &reply_pdu);
2755 prs_mem_free(&reply_pdu);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 tevent_req_nterror(req, status);
2759 break;
2761 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2762 /* Need to send alter context request and reply. */
2763 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2764 &reply_pdu);
2765 prs_mem_free(&reply_pdu);
2766 if (!NT_STATUS_IS_OK(status)) {
2767 tevent_req_nterror(req, status);
2769 break;
2771 case PIPE_AUTH_TYPE_KRB5:
2772 /* */
2774 default:
2775 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2776 (unsigned int)state->cli->auth->auth_type));
2777 prs_mem_free(&reply_pdu);
2778 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2782 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2783 struct rpc_pipe_bind_state *state,
2784 struct rpc_hdr_info *phdr,
2785 prs_struct *reply_pdu)
2787 DATA_BLOB server_response = data_blob_null;
2788 DATA_BLOB client_reply = data_blob_null;
2789 struct rpc_hdr_auth_info hdr_auth;
2790 struct tevent_req *subreq;
2791 NTSTATUS status;
2793 if ((phdr->auth_len == 0)
2794 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2795 return NT_STATUS_INVALID_PARAMETER;
2798 if (!prs_set_offset(
2799 reply_pdu,
2800 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2801 return NT_STATUS_INVALID_PARAMETER;
2804 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2805 return NT_STATUS_INVALID_PARAMETER;
2808 /* TODO - check auth_type/auth_level match. */
2810 server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2811 prs_copy_data_out((char *)server_response.data, reply_pdu,
2812 phdr->auth_len);
2814 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2815 server_response, &client_reply);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2819 "blob failed: %s.\n", nt_errstr(status)));
2820 return status;
2823 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2825 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2826 state->cli->auth->auth_type,
2827 state->cli->auth->auth_level,
2828 &client_reply, &state->rpc_out);
2829 data_blob_free(&client_reply);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 return status;
2835 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2836 (uint8_t *)prs_data_p(&state->rpc_out),
2837 prs_offset(&state->rpc_out));
2838 if (subreq == NULL) {
2839 return NT_STATUS_NO_MEMORY;
2841 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2842 return NT_STATUS_OK;
2845 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2847 struct tevent_req *req = tevent_req_callback_data(
2848 subreq, struct tevent_req);
2849 NTSTATUS status;
2851 status = rpc_write_recv(subreq);
2852 TALLOC_FREE(subreq);
2853 if (!NT_STATUS_IS_OK(status)) {
2854 tevent_req_nterror(req, status);
2855 return;
2857 tevent_req_done(req);
2860 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2861 struct rpc_pipe_bind_state *state,
2862 struct rpc_hdr_info *phdr,
2863 prs_struct *reply_pdu)
2865 DATA_BLOB server_spnego_response = data_blob_null;
2866 DATA_BLOB server_ntlm_response = data_blob_null;
2867 DATA_BLOB client_reply = data_blob_null;
2868 DATA_BLOB tmp_blob = data_blob_null;
2869 RPC_HDR_AUTH hdr_auth;
2870 struct tevent_req *subreq;
2871 NTSTATUS status;
2873 if ((phdr->auth_len == 0)
2874 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2875 return NT_STATUS_INVALID_PARAMETER;
2878 /* Process the returned NTLMSSP blob first. */
2879 if (!prs_set_offset(
2880 reply_pdu,
2881 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2882 return NT_STATUS_INVALID_PARAMETER;
2885 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2886 return NT_STATUS_INVALID_PARAMETER;
2889 server_spnego_response = data_blob(NULL, phdr->auth_len);
2890 prs_copy_data_out((char *)server_spnego_response.data,
2891 reply_pdu, phdr->auth_len);
2894 * The server might give us back two challenges - tmp_blob is for the
2895 * second.
2897 if (!spnego_parse_challenge(server_spnego_response,
2898 &server_ntlm_response, &tmp_blob)) {
2899 data_blob_free(&server_spnego_response);
2900 data_blob_free(&server_ntlm_response);
2901 data_blob_free(&tmp_blob);
2902 return NT_STATUS_INVALID_PARAMETER;
2905 /* We're finished with the server spnego response and the tmp_blob. */
2906 data_blob_free(&server_spnego_response);
2907 data_blob_free(&tmp_blob);
2909 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2910 server_ntlm_response, &client_reply);
2912 /* Finished with the server_ntlm response */
2913 data_blob_free(&server_ntlm_response);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2917 "using server blob failed.\n"));
2918 data_blob_free(&client_reply);
2919 return status;
2922 /* SPNEGO wrap the client reply. */
2923 tmp_blob = spnego_gen_auth(client_reply);
2924 data_blob_free(&client_reply);
2925 client_reply = tmp_blob;
2926 tmp_blob = data_blob_null;
2928 /* Now prepare the alter context pdu. */
2929 prs_init_empty(&state->rpc_out, state, MARSHALL);
2931 status = create_rpc_alter_context(state->rpc_call_id,
2932 &state->cli->abstract_syntax,
2933 &state->cli->transfer_syntax,
2934 state->cli->auth->auth_level,
2935 &client_reply,
2936 &state->rpc_out);
2937 data_blob_free(&client_reply);
2939 if (!NT_STATUS_IS_OK(status)) {
2940 return status;
2943 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2944 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2945 if (subreq == NULL) {
2946 return NT_STATUS_NO_MEMORY;
2948 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2949 return NT_STATUS_OK;
2952 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2954 struct tevent_req *req = tevent_req_callback_data(
2955 subreq, struct tevent_req);
2956 struct rpc_pipe_bind_state *state = tevent_req_data(
2957 req, struct rpc_pipe_bind_state);
2958 DATA_BLOB server_spnego_response = data_blob_null;
2959 DATA_BLOB tmp_blob = data_blob_null;
2960 prs_struct reply_pdu;
2961 struct rpc_hdr_info hdr;
2962 struct rpc_hdr_auth_info hdr_auth;
2963 NTSTATUS status;
2965 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2966 TALLOC_FREE(subreq);
2967 if (!NT_STATUS_IS_OK(status)) {
2968 tevent_req_nterror(req, status);
2969 return;
2972 /* Get the auth blob from the reply. */
2973 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) {
2974 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
2975 "unmarshall RPC_HDR.\n"));
2976 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2977 return;
2980 if (!prs_set_offset(
2981 &reply_pdu,
2982 hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
2983 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2984 return;
2987 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
2988 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2989 return;
2992 server_spnego_response = data_blob(NULL, hdr.auth_len);
2993 prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
2994 hdr.auth_len);
2996 /* Check we got a valid auth response. */
2997 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
2998 OID_NTLMSSP, &tmp_blob)) {
2999 data_blob_free(&server_spnego_response);
3000 data_blob_free(&tmp_blob);
3001 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3002 return;
3005 data_blob_free(&server_spnego_response);
3006 data_blob_free(&tmp_blob);
3008 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
3009 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
3010 tevent_req_done(req);
3013 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3015 return tevent_req_simple_recv_ntstatus(req);
3018 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3019 struct cli_pipe_auth_data *auth)
3021 TALLOC_CTX *frame = talloc_stackframe();
3022 struct event_context *ev;
3023 struct tevent_req *req;
3024 NTSTATUS status = NT_STATUS_OK;
3026 ev = event_context_init(frame);
3027 if (ev == NULL) {
3028 status = NT_STATUS_NO_MEMORY;
3029 goto fail;
3032 req = rpc_pipe_bind_send(frame, ev, cli, auth);
3033 if (req == NULL) {
3034 status = NT_STATUS_NO_MEMORY;
3035 goto fail;
3038 if (!tevent_req_poll(req, ev)) {
3039 status = map_nt_error_from_unix(errno);
3040 goto fail;
3043 status = rpc_pipe_bind_recv(req);
3044 fail:
3045 TALLOC_FREE(frame);
3046 return status;
3049 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3050 unsigned int timeout)
3052 struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
3054 if (cli == NULL) {
3055 return 0;
3057 return cli_set_timeout(cli, timeout);
3060 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3062 struct cli_state *cli;
3064 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3065 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3066 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3067 return true;
3070 cli = rpc_pipe_np_smb_conn(rpc_cli);
3071 if (cli == NULL) {
3072 return false;
3074 E_md4hash(cli->password ? cli->password : "", nt_hash);
3075 return true;
3078 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3079 struct cli_pipe_auth_data **presult)
3081 struct cli_pipe_auth_data *result;
3083 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3084 if (result == NULL) {
3085 return NT_STATUS_NO_MEMORY;
3088 result->auth_type = PIPE_AUTH_TYPE_NONE;
3089 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3091 result->user_name = talloc_strdup(result, "");
3092 result->domain = talloc_strdup(result, "");
3093 if ((result->user_name == NULL) || (result->domain == NULL)) {
3094 TALLOC_FREE(result);
3095 return NT_STATUS_NO_MEMORY;
3098 *presult = result;
3099 return NT_STATUS_OK;
3102 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3104 ntlmssp_end(&auth->a_u.ntlmssp_state);
3105 return 0;
3108 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3109 enum pipe_auth_type auth_type,
3110 enum dcerpc_AuthLevel auth_level,
3111 const char *domain,
3112 const char *username,
3113 const char *password,
3114 struct cli_pipe_auth_data **presult)
3116 struct cli_pipe_auth_data *result;
3117 NTSTATUS status;
3119 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3120 if (result == NULL) {
3121 return NT_STATUS_NO_MEMORY;
3124 result->auth_type = auth_type;
3125 result->auth_level = auth_level;
3127 result->user_name = talloc_strdup(result, username);
3128 result->domain = talloc_strdup(result, domain);
3129 if ((result->user_name == NULL) || (result->domain == NULL)) {
3130 status = NT_STATUS_NO_MEMORY;
3131 goto fail;
3134 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
3135 if (!NT_STATUS_IS_OK(status)) {
3136 goto fail;
3139 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3141 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 goto fail;
3146 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3147 if (!NT_STATUS_IS_OK(status)) {
3148 goto fail;
3151 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3152 if (!NT_STATUS_IS_OK(status)) {
3153 goto fail;
3157 * Turn off sign+seal to allow selected auth level to turn it back on.
3159 result->a_u.ntlmssp_state->neg_flags &=
3160 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3162 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3163 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3164 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3165 result->a_u.ntlmssp_state->neg_flags
3166 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3169 *presult = result;
3170 return NT_STATUS_OK;
3172 fail:
3173 TALLOC_FREE(result);
3174 return status;
3177 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3178 enum dcerpc_AuthLevel auth_level,
3179 struct netlogon_creds_CredentialState *creds,
3180 struct cli_pipe_auth_data **presult)
3182 struct cli_pipe_auth_data *result;
3184 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3185 if (result == NULL) {
3186 return NT_STATUS_NO_MEMORY;
3189 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3190 result->auth_level = auth_level;
3192 result->user_name = talloc_strdup(result, "");
3193 result->domain = talloc_strdup(result, domain);
3194 if ((result->user_name == NULL) || (result->domain == NULL)) {
3195 goto fail;
3198 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3199 if (result->a_u.schannel_auth == NULL) {
3200 goto fail;
3203 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3204 result->a_u.schannel_auth->seq_num = 0;
3205 result->a_u.schannel_auth->initiator = true;
3206 result->a_u.schannel_auth->creds = creds;
3208 *presult = result;
3209 return NT_STATUS_OK;
3211 fail:
3212 TALLOC_FREE(result);
3213 return NT_STATUS_NO_MEMORY;
3216 #ifdef HAVE_KRB5
3217 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3219 data_blob_free(&auth->session_key);
3220 return 0;
3222 #endif
3224 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3225 enum dcerpc_AuthLevel auth_level,
3226 const char *service_princ,
3227 const char *username,
3228 const char *password,
3229 struct cli_pipe_auth_data **presult)
3231 #ifdef HAVE_KRB5
3232 struct cli_pipe_auth_data *result;
3234 if ((username != NULL) && (password != NULL)) {
3235 int ret = kerberos_kinit_password(username, password, 0, NULL);
3236 if (ret != 0) {
3237 return NT_STATUS_ACCESS_DENIED;
3241 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3242 if (result == NULL) {
3243 return NT_STATUS_NO_MEMORY;
3246 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3247 result->auth_level = auth_level;
3250 * Username / domain need fixing!
3252 result->user_name = talloc_strdup(result, "");
3253 result->domain = talloc_strdup(result, "");
3254 if ((result->user_name == NULL) || (result->domain == NULL)) {
3255 goto fail;
3258 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3259 result, struct kerberos_auth_struct);
3260 if (result->a_u.kerberos_auth == NULL) {
3261 goto fail;
3263 talloc_set_destructor(result->a_u.kerberos_auth,
3264 cli_auth_kerberos_data_destructor);
3266 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3267 result, service_princ);
3268 if (result->a_u.kerberos_auth->service_principal == NULL) {
3269 goto fail;
3272 *presult = result;
3273 return NT_STATUS_OK;
3275 fail:
3276 TALLOC_FREE(result);
3277 return NT_STATUS_NO_MEMORY;
3278 #else
3279 return NT_STATUS_NOT_SUPPORTED;
3280 #endif
3284 * Create an rpc pipe client struct, connecting to a tcp port.
3286 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3287 uint16_t port,
3288 const struct ndr_syntax_id *abstract_syntax,
3289 struct rpc_pipe_client **presult)
3291 struct rpc_pipe_client *result;
3292 struct sockaddr_storage addr;
3293 NTSTATUS status;
3294 int fd;
3296 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3297 if (result == NULL) {
3298 return NT_STATUS_NO_MEMORY;
3301 result->abstract_syntax = *abstract_syntax;
3302 result->transfer_syntax = ndr_transfer_syntax;
3303 result->dispatch = cli_do_rpc_ndr;
3304 result->dispatch_send = cli_do_rpc_ndr_send;
3305 result->dispatch_recv = cli_do_rpc_ndr_recv;
3307 result->desthost = talloc_strdup(result, host);
3308 result->srv_name_slash = talloc_asprintf_strupper_m(
3309 result, "\\\\%s", result->desthost);
3310 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3311 status = NT_STATUS_NO_MEMORY;
3312 goto fail;
3315 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3316 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3318 if (!resolve_name(host, &addr, 0, false)) {
3319 status = NT_STATUS_NOT_FOUND;
3320 goto fail;
3323 status = open_socket_out(&addr, port, 60, &fd);
3324 if (!NT_STATUS_IS_OK(status)) {
3325 goto fail;
3327 set_socket_options(fd, lp_socket_options());
3329 status = rpc_transport_sock_init(result, fd, &result->transport);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 close(fd);
3332 goto fail;
3335 result->transport->transport = NCACN_IP_TCP;
3337 *presult = result;
3338 return NT_STATUS_OK;
3340 fail:
3341 TALLOC_FREE(result);
3342 return status;
3346 * Determine the tcp port on which a dcerpc interface is listening
3347 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3348 * target host.
3350 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3351 const struct ndr_syntax_id *abstract_syntax,
3352 uint16_t *pport)
3354 NTSTATUS status;
3355 struct rpc_pipe_client *epm_pipe = NULL;
3356 struct cli_pipe_auth_data *auth = NULL;
3357 struct dcerpc_binding *map_binding = NULL;
3358 struct dcerpc_binding *res_binding = NULL;
3359 struct epm_twr_t *map_tower = NULL;
3360 struct epm_twr_t *res_towers = NULL;
3361 struct policy_handle *entry_handle = NULL;
3362 uint32_t num_towers = 0;
3363 uint32_t max_towers = 1;
3364 struct epm_twr_p_t towers;
3365 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3367 if (pport == NULL) {
3368 status = NT_STATUS_INVALID_PARAMETER;
3369 goto done;
3372 /* open the connection to the endpoint mapper */
3373 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3374 &ndr_table_epmapper.syntax_id,
3375 &epm_pipe);
3377 if (!NT_STATUS_IS_OK(status)) {
3378 goto done;
3381 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3382 if (!NT_STATUS_IS_OK(status)) {
3383 goto done;
3386 status = rpc_pipe_bind(epm_pipe, auth);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 goto done;
3391 /* create tower for asking the epmapper */
3393 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3394 if (map_binding == NULL) {
3395 status = NT_STATUS_NO_MEMORY;
3396 goto done;
3399 map_binding->transport = NCACN_IP_TCP;
3400 map_binding->object = *abstract_syntax;
3401 map_binding->host = host; /* needed? */
3402 map_binding->endpoint = "0"; /* correct? needed? */
3404 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3405 if (map_tower == NULL) {
3406 status = NT_STATUS_NO_MEMORY;
3407 goto done;
3410 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3411 &(map_tower->tower));
3412 if (!NT_STATUS_IS_OK(status)) {
3413 goto done;
3416 /* allocate further parameters for the epm_Map call */
3418 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3419 if (res_towers == NULL) {
3420 status = NT_STATUS_NO_MEMORY;
3421 goto done;
3423 towers.twr = res_towers;
3425 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3426 if (entry_handle == NULL) {
3427 status = NT_STATUS_NO_MEMORY;
3428 goto done;
3431 /* ask the endpoint mapper for the port */
3433 status = rpccli_epm_Map(epm_pipe,
3434 tmp_ctx,
3435 CONST_DISCARD(struct GUID *,
3436 &(abstract_syntax->uuid)),
3437 map_tower,
3438 entry_handle,
3439 max_towers,
3440 &num_towers,
3441 &towers);
3443 if (!NT_STATUS_IS_OK(status)) {
3444 goto done;
3447 if (num_towers != 1) {
3448 status = NT_STATUS_UNSUCCESSFUL;
3449 goto done;
3452 /* extract the port from the answer */
3454 status = dcerpc_binding_from_tower(tmp_ctx,
3455 &(towers.twr->tower),
3456 &res_binding);
3457 if (!NT_STATUS_IS_OK(status)) {
3458 goto done;
3461 /* are further checks here necessary? */
3462 if (res_binding->transport != NCACN_IP_TCP) {
3463 status = NT_STATUS_UNSUCCESSFUL;
3464 goto done;
3467 *pport = (uint16_t)atoi(res_binding->endpoint);
3469 done:
3470 TALLOC_FREE(tmp_ctx);
3471 return status;
3475 * Create a rpc pipe client struct, connecting to a host via tcp.
3476 * The port is determined by asking the endpoint mapper on the given
3477 * host.
3479 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3480 const struct ndr_syntax_id *abstract_syntax,
3481 struct rpc_pipe_client **presult)
3483 NTSTATUS status;
3484 uint16_t port = 0;
3486 *presult = NULL;
3488 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3489 if (!NT_STATUS_IS_OK(status)) {
3490 goto done;
3493 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
3494 abstract_syntax, presult);
3496 done:
3497 return status;
3500 /********************************************************************
3501 Create a rpc pipe client struct, connecting to a unix domain socket
3502 ********************************************************************/
3503 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3504 const struct ndr_syntax_id *abstract_syntax,
3505 struct rpc_pipe_client **presult)
3507 struct rpc_pipe_client *result;
3508 struct sockaddr_un addr;
3509 NTSTATUS status;
3510 int fd;
3512 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3513 if (result == NULL) {
3514 return NT_STATUS_NO_MEMORY;
3517 result->abstract_syntax = *abstract_syntax;
3518 result->transfer_syntax = ndr_transfer_syntax;
3519 result->dispatch = cli_do_rpc_ndr;
3520 result->dispatch_send = cli_do_rpc_ndr_send;
3521 result->dispatch_recv = cli_do_rpc_ndr_recv;
3523 result->desthost = get_myname(result);
3524 result->srv_name_slash = talloc_asprintf_strupper_m(
3525 result, "\\\\%s", result->desthost);
3526 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3527 status = NT_STATUS_NO_MEMORY;
3528 goto fail;
3531 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3532 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3534 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3535 if (fd == -1) {
3536 status = map_nt_error_from_unix(errno);
3537 goto fail;
3540 ZERO_STRUCT(addr);
3541 addr.sun_family = AF_UNIX;
3542 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3544 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3545 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3546 strerror(errno)));
3547 close(fd);
3548 return map_nt_error_from_unix(errno);
3551 status = rpc_transport_sock_init(result, fd, &result->transport);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 close(fd);
3554 goto fail;
3557 result->transport->transport = NCALRPC;
3559 *presult = result;
3560 return NT_STATUS_OK;
3562 fail:
3563 TALLOC_FREE(result);
3564 return status;
3567 static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p)
3569 struct cli_state *cli;
3571 cli = rpc_pipe_np_smb_conn(p);
3572 if (cli != NULL) {
3573 DLIST_REMOVE(cli->pipe_list, p);
3575 return 0;
3578 /****************************************************************************
3579 Open a named pipe over SMB to a remote server.
3581 * CAVEAT CALLER OF THIS FUNCTION:
3582 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3583 * so be sure that this function is called AFTER any structure (vs pointer)
3584 * assignment of the cli. In particular, libsmbclient does structure
3585 * assignments of cli, which invalidates the data in the returned
3586 * rpc_pipe_client if this function is called before the structure assignment
3587 * of cli.
3589 ****************************************************************************/
3591 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3592 const struct ndr_syntax_id *abstract_syntax,
3593 struct rpc_pipe_client **presult)
3595 struct rpc_pipe_client *result;
3596 NTSTATUS status;
3598 /* sanity check to protect against crashes */
3600 if ( !cli ) {
3601 return NT_STATUS_INVALID_HANDLE;
3604 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3605 if (result == NULL) {
3606 return NT_STATUS_NO_MEMORY;
3609 result->abstract_syntax = *abstract_syntax;
3610 result->transfer_syntax = ndr_transfer_syntax;
3611 result->dispatch = cli_do_rpc_ndr;
3612 result->dispatch_send = cli_do_rpc_ndr_send;
3613 result->dispatch_recv = cli_do_rpc_ndr_recv;
3614 result->desthost = talloc_strdup(result, cli->desthost);
3615 result->srv_name_slash = talloc_asprintf_strupper_m(
3616 result, "\\\\%s", result->desthost);
3618 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3619 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3621 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3622 TALLOC_FREE(result);
3623 return NT_STATUS_NO_MEMORY;
3626 status = rpc_transport_np_init(result, cli, abstract_syntax,
3627 &result->transport);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 TALLOC_FREE(result);
3630 return status;
3633 result->transport->transport = NCACN_NP;
3635 DLIST_ADD(cli->pipe_list, result);
3636 talloc_set_destructor(result, rpc_pipe_client_np_destructor);
3638 *presult = result;
3639 return NT_STATUS_OK;
3642 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3643 struct rpc_cli_smbd_conn *conn,
3644 const struct ndr_syntax_id *syntax,
3645 struct rpc_pipe_client **presult)
3647 struct rpc_pipe_client *result;
3648 struct cli_pipe_auth_data *auth;
3649 NTSTATUS status;
3651 result = talloc(mem_ctx, struct rpc_pipe_client);
3652 if (result == NULL) {
3653 return NT_STATUS_NO_MEMORY;
3655 result->abstract_syntax = *syntax;
3656 result->transfer_syntax = ndr_transfer_syntax;
3657 result->dispatch = cli_do_rpc_ndr;
3658 result->dispatch_send = cli_do_rpc_ndr_send;
3659 result->dispatch_recv = cli_do_rpc_ndr_recv;
3660 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3661 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3663 result->desthost = talloc_strdup(result, global_myname());
3664 result->srv_name_slash = talloc_asprintf_strupper_m(
3665 result, "\\\\%s", global_myname());
3666 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3667 TALLOC_FREE(result);
3668 return NT_STATUS_NO_MEMORY;
3671 status = rpc_transport_smbd_init(result, conn, syntax,
3672 &result->transport);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3675 nt_errstr(status)));
3676 TALLOC_FREE(result);
3677 return status;
3680 status = rpccli_anon_bind_data(result, &auth);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3683 nt_errstr(status)));
3684 TALLOC_FREE(result);
3685 return status;
3688 status = rpc_pipe_bind(result, auth);
3689 if (!NT_STATUS_IS_OK(status)) {
3690 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3691 TALLOC_FREE(result);
3692 return status;
3695 result->transport->transport = NCACN_INTERNAL;
3697 *presult = result;
3698 return NT_STATUS_OK;
3701 /****************************************************************************
3702 Open a pipe to a remote server.
3703 ****************************************************************************/
3705 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3706 enum dcerpc_transport_t transport,
3707 const struct ndr_syntax_id *interface,
3708 struct rpc_pipe_client **presult)
3710 switch (transport) {
3711 case NCACN_IP_TCP:
3712 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3713 presult);
3714 case NCACN_NP:
3715 return rpc_pipe_open_np(cli, interface, presult);
3716 default:
3717 return NT_STATUS_NOT_IMPLEMENTED;
3721 /****************************************************************************
3722 Open a named pipe to an SMB server and bind anonymously.
3723 ****************************************************************************/
3725 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3726 enum dcerpc_transport_t transport,
3727 const struct ndr_syntax_id *interface,
3728 struct rpc_pipe_client **presult)
3730 struct rpc_pipe_client *result;
3731 struct cli_pipe_auth_data *auth;
3732 NTSTATUS status;
3734 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3735 if (!NT_STATUS_IS_OK(status)) {
3736 return status;
3739 status = rpccli_anon_bind_data(result, &auth);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3742 nt_errstr(status)));
3743 TALLOC_FREE(result);
3744 return status;
3748 * This is a bit of an abstraction violation due to the fact that an
3749 * anonymous bind on an authenticated SMB inherits the user/domain
3750 * from the enclosing SMB creds
3753 TALLOC_FREE(auth->user_name);
3754 TALLOC_FREE(auth->domain);
3756 auth->user_name = talloc_strdup(auth, cli->user_name);
3757 auth->domain = talloc_strdup(auth, cli->domain);
3758 auth->user_session_key = data_blob_talloc(auth,
3759 cli->user_session_key.data,
3760 cli->user_session_key.length);
3762 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3763 TALLOC_FREE(result);
3764 return NT_STATUS_NO_MEMORY;
3767 status = rpc_pipe_bind(result, auth);
3768 if (!NT_STATUS_IS_OK(status)) {
3769 int lvl = 0;
3770 if (ndr_syntax_id_equal(interface,
3771 &ndr_table_dssetup.syntax_id)) {
3772 /* non AD domains just don't have this pipe, avoid
3773 * level 0 statement in that case - gd */
3774 lvl = 3;
3776 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3777 "%s failed with error %s\n",
3778 get_pipe_name_from_syntax(talloc_tos(), interface),
3779 nt_errstr(status) ));
3780 TALLOC_FREE(result);
3781 return status;
3784 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3785 "%s and bound anonymously.\n",
3786 get_pipe_name_from_syntax(talloc_tos(), interface),
3787 cli->desthost));
3789 *presult = result;
3790 return NT_STATUS_OK;
3793 /****************************************************************************
3794 ****************************************************************************/
3796 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3797 const struct ndr_syntax_id *interface,
3798 struct rpc_pipe_client **presult)
3800 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3801 interface, presult);
3804 /****************************************************************************
3805 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3806 ****************************************************************************/
3808 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3809 const struct ndr_syntax_id *interface,
3810 enum dcerpc_transport_t transport,
3811 enum pipe_auth_type auth_type,
3812 enum dcerpc_AuthLevel auth_level,
3813 const char *domain,
3814 const char *username,
3815 const char *password,
3816 struct rpc_pipe_client **presult)
3818 struct rpc_pipe_client *result;
3819 struct cli_pipe_auth_data *auth;
3820 NTSTATUS status;
3822 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3823 if (!NT_STATUS_IS_OK(status)) {
3824 return status;
3827 status = rpccli_ntlmssp_bind_data(
3828 result, auth_type, auth_level, domain, username,
3829 password, &auth);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3832 nt_errstr(status)));
3833 goto err;
3836 status = rpc_pipe_bind(result, auth);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3839 nt_errstr(status) ));
3840 goto err;
3843 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3844 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3845 get_pipe_name_from_syntax(talloc_tos(), interface),
3846 cli->desthost, domain, username ));
3848 *presult = result;
3849 return NT_STATUS_OK;
3851 err:
3853 TALLOC_FREE(result);
3854 return status;
3857 /****************************************************************************
3858 External interface.
3859 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3860 ****************************************************************************/
3862 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3863 const struct ndr_syntax_id *interface,
3864 enum dcerpc_transport_t transport,
3865 enum dcerpc_AuthLevel auth_level,
3866 const char *domain,
3867 const char *username,
3868 const char *password,
3869 struct rpc_pipe_client **presult)
3871 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3872 interface,
3873 transport,
3874 PIPE_AUTH_TYPE_NTLMSSP,
3875 auth_level,
3876 domain,
3877 username,
3878 password,
3879 presult);
3882 /****************************************************************************
3883 External interface.
3884 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3885 ****************************************************************************/
3887 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3888 const struct ndr_syntax_id *interface,
3889 enum dcerpc_transport_t transport,
3890 enum dcerpc_AuthLevel auth_level,
3891 const char *domain,
3892 const char *username,
3893 const char *password,
3894 struct rpc_pipe_client **presult)
3896 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3897 interface,
3898 transport,
3899 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3900 auth_level,
3901 domain,
3902 username,
3903 password,
3904 presult);
3907 /****************************************************************************
3908 Get a the schannel session key out of an already opened netlogon pipe.
3909 ****************************************************************************/
3910 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3911 struct cli_state *cli,
3912 const char *domain,
3913 uint32 *pneg_flags)
3915 enum netr_SchannelType sec_chan_type = 0;
3916 unsigned char machine_pwd[16];
3917 const char *machine_account;
3918 NTSTATUS status;
3920 /* Get the machine account credentials from secrets.tdb. */
3921 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3922 &sec_chan_type))
3924 DEBUG(0, ("get_schannel_session_key: could not fetch "
3925 "trust account password for domain '%s'\n",
3926 domain));
3927 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3930 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3931 cli->desthost, /* server name */
3932 domain, /* domain */
3933 global_myname(), /* client name */
3934 machine_account, /* machine account name */
3935 machine_pwd,
3936 sec_chan_type,
3937 pneg_flags);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 DEBUG(3, ("get_schannel_session_key_common: "
3941 "rpccli_netlogon_setup_creds failed with result %s "
3942 "to server %s, domain %s, machine account %s.\n",
3943 nt_errstr(status), cli->desthost, domain,
3944 machine_account ));
3945 return status;
3948 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3949 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3950 cli->desthost));
3951 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3954 return NT_STATUS_OK;;
3957 /****************************************************************************
3958 Open a netlogon pipe and get the schannel session key.
3959 Now exposed to external callers.
3960 ****************************************************************************/
3963 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3964 const char *domain,
3965 uint32 *pneg_flags,
3966 struct rpc_pipe_client **presult)
3968 struct rpc_pipe_client *netlogon_pipe = NULL;
3969 NTSTATUS status;
3971 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3972 &netlogon_pipe);
3973 if (!NT_STATUS_IS_OK(status)) {
3974 return status;
3977 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3978 pneg_flags);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 TALLOC_FREE(netlogon_pipe);
3981 return status;
3984 *presult = netlogon_pipe;
3985 return NT_STATUS_OK;
3988 /****************************************************************************
3989 External interface.
3990 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3991 using session_key. sign and seal.
3993 The *pdc will be stolen onto this new pipe
3994 ****************************************************************************/
3996 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3997 const struct ndr_syntax_id *interface,
3998 enum dcerpc_transport_t transport,
3999 enum dcerpc_AuthLevel auth_level,
4000 const char *domain,
4001 struct netlogon_creds_CredentialState **pdc,
4002 struct rpc_pipe_client **presult)
4004 struct rpc_pipe_client *result;
4005 struct cli_pipe_auth_data *auth;
4006 NTSTATUS status;
4008 status = cli_rpc_pipe_open(cli, transport, interface, &result);
4009 if (!NT_STATUS_IS_OK(status)) {
4010 return status;
4013 status = rpccli_schannel_bind_data(result, domain, auth_level,
4014 *pdc, &auth);
4015 if (!NT_STATUS_IS_OK(status)) {
4016 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4017 nt_errstr(status)));
4018 TALLOC_FREE(result);
4019 return status;
4022 status = rpc_pipe_bind(result, auth);
4023 if (!NT_STATUS_IS_OK(status)) {
4024 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4025 "cli_rpc_pipe_bind failed with error %s\n",
4026 nt_errstr(status) ));
4027 TALLOC_FREE(result);
4028 return status;
4032 * The credentials on a new netlogon pipe are the ones we are passed
4033 * in - reference them in
4035 result->dc = talloc_move(result, pdc);
4037 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4038 "for domain %s and bound using schannel.\n",
4039 get_pipe_name_from_syntax(talloc_tos(), interface),
4040 cli->desthost, domain ));
4042 *presult = result;
4043 return NT_STATUS_OK;
4046 /****************************************************************************
4047 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4048 Fetch the session key ourselves using a temporary netlogon pipe. This
4049 version uses an ntlmssp auth bound netlogon pipe to get the key.
4050 ****************************************************************************/
4052 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4053 const char *domain,
4054 const char *username,
4055 const char *password,
4056 uint32 *pneg_flags,
4057 struct rpc_pipe_client **presult)
4059 struct rpc_pipe_client *netlogon_pipe = NULL;
4060 NTSTATUS status;
4062 status = cli_rpc_pipe_open_spnego_ntlmssp(
4063 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4064 DCERPC_AUTH_LEVEL_PRIVACY,
4065 domain, username, password, &netlogon_pipe);
4066 if (!NT_STATUS_IS_OK(status)) {
4067 return status;
4070 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4071 pneg_flags);
4072 if (!NT_STATUS_IS_OK(status)) {
4073 TALLOC_FREE(netlogon_pipe);
4074 return status;
4077 *presult = netlogon_pipe;
4078 return NT_STATUS_OK;
4081 /****************************************************************************
4082 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4083 Fetch the session key ourselves using a temporary netlogon pipe. This version
4084 uses an ntlmssp bind to get the session key.
4085 ****************************************************************************/
4087 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4088 const struct ndr_syntax_id *interface,
4089 enum dcerpc_transport_t transport,
4090 enum dcerpc_AuthLevel auth_level,
4091 const char *domain,
4092 const char *username,
4093 const char *password,
4094 struct rpc_pipe_client **presult)
4096 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4097 struct rpc_pipe_client *netlogon_pipe = NULL;
4098 struct rpc_pipe_client *result = NULL;
4099 NTSTATUS status;
4101 status = get_schannel_session_key_auth_ntlmssp(
4102 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4105 "key from server %s for domain %s.\n",
4106 cli->desthost, domain ));
4107 return status;
4110 status = cli_rpc_pipe_open_schannel_with_key(
4111 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4112 &result);
4114 /* Now we've bound using the session key we can close the netlog pipe. */
4115 TALLOC_FREE(netlogon_pipe);
4117 if (NT_STATUS_IS_OK(status)) {
4118 *presult = result;
4120 return status;
4123 /****************************************************************************
4124 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4125 Fetch the session key ourselves using a temporary netlogon pipe.
4126 ****************************************************************************/
4128 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4129 const struct ndr_syntax_id *interface,
4130 enum dcerpc_transport_t transport,
4131 enum dcerpc_AuthLevel auth_level,
4132 const char *domain,
4133 struct rpc_pipe_client **presult)
4135 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4136 struct rpc_pipe_client *netlogon_pipe = NULL;
4137 struct rpc_pipe_client *result = NULL;
4138 NTSTATUS status;
4140 status = get_schannel_session_key(cli, domain, &neg_flags,
4141 &netlogon_pipe);
4142 if (!NT_STATUS_IS_OK(status)) {
4143 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4144 "key from server %s for domain %s.\n",
4145 cli->desthost, domain ));
4146 return status;
4149 status = cli_rpc_pipe_open_schannel_with_key(
4150 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4151 &result);
4153 /* Now we've bound using the session key we can close the netlog pipe. */
4154 TALLOC_FREE(netlogon_pipe);
4156 if (NT_STATUS_IS_OK(status)) {
4157 *presult = result;
4160 return NT_STATUS_OK;
4163 /****************************************************************************
4164 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4165 The idea is this can be called with service_princ, username and password all
4166 NULL so long as the caller has a TGT.
4167 ****************************************************************************/
4169 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4170 const struct ndr_syntax_id *interface,
4171 enum dcerpc_AuthLevel auth_level,
4172 const char *service_princ,
4173 const char *username,
4174 const char *password,
4175 struct rpc_pipe_client **presult)
4177 #ifdef HAVE_KRB5
4178 struct rpc_pipe_client *result;
4179 struct cli_pipe_auth_data *auth;
4180 NTSTATUS status;
4182 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 return status;
4187 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4188 username, password, &auth);
4189 if (!NT_STATUS_IS_OK(status)) {
4190 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4191 nt_errstr(status)));
4192 TALLOC_FREE(result);
4193 return status;
4196 status = rpc_pipe_bind(result, auth);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4199 "with error %s\n", nt_errstr(status)));
4200 TALLOC_FREE(result);
4201 return status;
4204 *presult = result;
4205 return NT_STATUS_OK;
4206 #else
4207 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4208 return NT_STATUS_NOT_IMPLEMENTED;
4209 #endif
4212 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4213 struct rpc_pipe_client *cli,
4214 DATA_BLOB *session_key)
4216 if (!session_key || !cli) {
4217 return NT_STATUS_INVALID_PARAMETER;
4220 if (!cli->auth) {
4221 return NT_STATUS_INVALID_PARAMETER;
4224 switch (cli->auth->auth_type) {
4225 case PIPE_AUTH_TYPE_SCHANNEL:
4226 *session_key = data_blob_talloc(mem_ctx,
4227 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4228 break;
4229 case PIPE_AUTH_TYPE_NTLMSSP:
4230 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4231 *session_key = data_blob_talloc(mem_ctx,
4232 cli->auth->a_u.ntlmssp_state->session_key.data,
4233 cli->auth->a_u.ntlmssp_state->session_key.length);
4234 break;
4235 case PIPE_AUTH_TYPE_KRB5:
4236 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4237 *session_key = data_blob_talloc(mem_ctx,
4238 cli->auth->a_u.kerberos_auth->session_key.data,
4239 cli->auth->a_u.kerberos_auth->session_key.length);
4240 break;
4241 case PIPE_AUTH_TYPE_NONE:
4242 *session_key = data_blob_talloc(mem_ctx,
4243 cli->auth->user_session_key.data,
4244 cli->auth->user_session_key.length);
4245 break;
4246 default:
4247 return NT_STATUS_NO_USER_SESSION_KEY;
4250 return NT_STATUS_OK;