s4:upgradeschema.py Cleanup
[Samba/ekacnet.git] / source3 / rpc_client / cli_pipe.c
blob084bbef44c4e1b012cb4c5234368b4633b274316
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 /********************************************************************
199 Map internal value to wire value.
200 ********************************************************************/
202 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
204 switch (auth_type) {
206 case PIPE_AUTH_TYPE_NONE:
207 return DCERPC_AUTH_TYPE_NONE;
209 case PIPE_AUTH_TYPE_NTLMSSP:
210 return DCERPC_AUTH_TYPE_NTLMSSP;
212 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
213 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
214 return DCERPC_AUTH_TYPE_SPNEGO;
216 case PIPE_AUTH_TYPE_SCHANNEL:
217 return DCERPC_AUTH_TYPE_SCHANNEL;
219 case PIPE_AUTH_TYPE_KRB5:
220 return DCERPC_AUTH_TYPE_KRB5;
222 default:
223 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
224 "auth type %u\n",
225 (unsigned int)auth_type ));
226 break;
228 return -1;
231 /********************************************************************
232 Pipe description for a DEBUG
233 ********************************************************************/
234 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
235 struct rpc_pipe_client *cli)
237 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
238 if (result == NULL) {
239 return "pipe";
241 return result;
244 /********************************************************************
245 Rpc pipe call id.
246 ********************************************************************/
248 static uint32 get_rpc_call_id(void)
250 static uint32 call_id = 0;
251 return ++call_id;
255 * Realloc pdu to have a least "size" bytes
258 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
260 size_t extra_size;
262 if (prs_data_size(pdu) >= size) {
263 return true;
266 extra_size = size - prs_data_size(pdu);
268 if (!prs_force_grow(pdu, extra_size)) {
269 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
270 "%d bytes.\n", (int)extra_size));
271 return false;
274 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
275 (int)extra_size, prs_data_size(pdu)));
276 return true;
280 /*******************************************************************
281 Use SMBreadX to get rest of one fragment's worth of rpc data.
282 Reads the whole size or give an error message
283 ********************************************************************/
285 struct rpc_read_state {
286 struct event_context *ev;
287 struct rpc_cli_transport *transport;
288 uint8_t *data;
289 size_t size;
290 size_t num_read;
293 static void rpc_read_done(struct tevent_req *subreq);
295 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
296 struct event_context *ev,
297 struct rpc_cli_transport *transport,
298 uint8_t *data, size_t size)
300 struct tevent_req *req, *subreq;
301 struct rpc_read_state *state;
303 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
304 if (req == NULL) {
305 return NULL;
307 state->ev = ev;
308 state->transport = transport;
309 state->data = data;
310 state->size = size;
311 state->num_read = 0;
313 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
315 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
316 transport->priv);
317 if (subreq == NULL) {
318 goto fail;
320 tevent_req_set_callback(subreq, rpc_read_done, req);
321 return req;
323 fail:
324 TALLOC_FREE(req);
325 return NULL;
328 static void rpc_read_done(struct tevent_req *subreq)
330 struct tevent_req *req = tevent_req_callback_data(
331 subreq, struct tevent_req);
332 struct rpc_read_state *state = tevent_req_data(
333 req, struct rpc_read_state);
334 NTSTATUS status;
335 ssize_t received;
337 status = state->transport->read_recv(subreq, &received);
338 TALLOC_FREE(subreq);
339 if (!NT_STATUS_IS_OK(status)) {
340 tevent_req_nterror(req, status);
341 return;
344 state->num_read += received;
345 if (state->num_read == state->size) {
346 tevent_req_done(req);
347 return;
350 subreq = state->transport->read_send(state, state->ev,
351 state->data + state->num_read,
352 state->size - state->num_read,
353 state->transport->priv);
354 if (tevent_req_nomem(subreq, req)) {
355 return;
357 tevent_req_set_callback(subreq, rpc_read_done, req);
360 static NTSTATUS rpc_read_recv(struct tevent_req *req)
362 return tevent_req_simple_recv_ntstatus(req);
365 struct rpc_write_state {
366 struct event_context *ev;
367 struct rpc_cli_transport *transport;
368 const uint8_t *data;
369 size_t size;
370 size_t num_written;
373 static void rpc_write_done(struct tevent_req *subreq);
375 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
376 struct event_context *ev,
377 struct rpc_cli_transport *transport,
378 const uint8_t *data, size_t size)
380 struct tevent_req *req, *subreq;
381 struct rpc_write_state *state;
383 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
384 if (req == NULL) {
385 return NULL;
387 state->ev = ev;
388 state->transport = transport;
389 state->data = data;
390 state->size = size;
391 state->num_written = 0;
393 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
395 subreq = transport->write_send(state, ev, data, size, transport->priv);
396 if (subreq == NULL) {
397 goto fail;
399 tevent_req_set_callback(subreq, rpc_write_done, req);
400 return req;
401 fail:
402 TALLOC_FREE(req);
403 return NULL;
406 static void rpc_write_done(struct tevent_req *subreq)
408 struct tevent_req *req = tevent_req_callback_data(
409 subreq, struct tevent_req);
410 struct rpc_write_state *state = tevent_req_data(
411 req, struct rpc_write_state);
412 NTSTATUS status;
413 ssize_t written;
415 status = state->transport->write_recv(subreq, &written);
416 TALLOC_FREE(subreq);
417 if (!NT_STATUS_IS_OK(status)) {
418 tevent_req_nterror(req, status);
419 return;
422 state->num_written += written;
424 if (state->num_written == state->size) {
425 tevent_req_done(req);
426 return;
429 subreq = state->transport->write_send(state, state->ev,
430 state->data + state->num_written,
431 state->size - state->num_written,
432 state->transport->priv);
433 if (tevent_req_nomem(subreq, req)) {
434 return;
436 tevent_req_set_callback(subreq, rpc_write_done, req);
439 static NTSTATUS rpc_write_recv(struct tevent_req *req)
441 return tevent_req_simple_recv_ntstatus(req);
445 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
446 struct rpc_hdr_info *prhdr,
447 prs_struct *pdu)
450 * This next call sets the endian bit correctly in current_pdu. We
451 * will propagate this to rbuf later.
454 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, pdu, 0)) {
455 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
456 return NT_STATUS_BUFFER_TOO_SMALL;
459 if (prhdr->frag_len > cli->max_recv_frag) {
460 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
461 " we only allow %d\n", (int)prhdr->frag_len,
462 (int)cli->max_recv_frag));
463 return NT_STATUS_BUFFER_TOO_SMALL;
466 return NT_STATUS_OK;
469 /****************************************************************************
470 Try and get a PDU's worth of data from current_pdu. If not, then read more
471 from the wire.
472 ****************************************************************************/
474 struct get_complete_frag_state {
475 struct event_context *ev;
476 struct rpc_pipe_client *cli;
477 struct rpc_hdr_info *prhdr;
478 prs_struct *pdu;
481 static void get_complete_frag_got_header(struct tevent_req *subreq);
482 static void get_complete_frag_got_rest(struct tevent_req *subreq);
484 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
485 struct event_context *ev,
486 struct rpc_pipe_client *cli,
487 struct rpc_hdr_info *prhdr,
488 prs_struct *pdu)
490 struct tevent_req *req, *subreq;
491 struct get_complete_frag_state *state;
492 uint32_t pdu_len;
493 NTSTATUS status;
495 req = tevent_req_create(mem_ctx, &state,
496 struct get_complete_frag_state);
497 if (req == NULL) {
498 return NULL;
500 state->ev = ev;
501 state->cli = cli;
502 state->prhdr = prhdr;
503 state->pdu = pdu;
505 pdu_len = prs_data_size(pdu);
506 if (pdu_len < RPC_HEADER_LEN) {
507 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
508 status = NT_STATUS_NO_MEMORY;
509 goto post_status;
511 subreq = rpc_read_send(
512 state, state->ev,
513 state->cli->transport,
514 (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
515 RPC_HEADER_LEN - pdu_len);
516 if (subreq == NULL) {
517 status = NT_STATUS_NO_MEMORY;
518 goto post_status;
520 tevent_req_set_callback(subreq, get_complete_frag_got_header,
521 req);
522 return req;
525 status = parse_rpc_header(cli, prhdr, pdu);
526 if (!NT_STATUS_IS_OK(status)) {
527 goto post_status;
531 * Ensure we have frag_len bytes of data.
533 if (pdu_len < prhdr->frag_len) {
534 if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
535 status = NT_STATUS_NO_MEMORY;
536 goto post_status;
538 subreq = rpc_read_send(state, state->ev,
539 state->cli->transport,
540 (uint8_t *)(prs_data_p(pdu) + pdu_len),
541 prhdr->frag_len - pdu_len);
542 if (subreq == NULL) {
543 status = NT_STATUS_NO_MEMORY;
544 goto post_status;
546 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
547 req);
548 return req;
551 status = NT_STATUS_OK;
552 post_status:
553 if (NT_STATUS_IS_OK(status)) {
554 tevent_req_done(req);
555 } else {
556 tevent_req_nterror(req, status);
558 return tevent_req_post(req, ev);
561 static void get_complete_frag_got_header(struct tevent_req *subreq)
563 struct tevent_req *req = tevent_req_callback_data(
564 subreq, struct tevent_req);
565 struct get_complete_frag_state *state = tevent_req_data(
566 req, struct get_complete_frag_state);
567 NTSTATUS status;
569 status = rpc_read_recv(subreq);
570 TALLOC_FREE(subreq);
571 if (!NT_STATUS_IS_OK(status)) {
572 tevent_req_nterror(req, status);
573 return;
576 status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
577 if (!NT_STATUS_IS_OK(status)) {
578 tevent_req_nterror(req, status);
579 return;
582 if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
583 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
584 return;
588 * We're here in this piece of code because we've read exactly
589 * RPC_HEADER_LEN bytes into state->pdu.
592 subreq = rpc_read_send(
593 state, state->ev, state->cli->transport,
594 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
595 state->prhdr->frag_len - RPC_HEADER_LEN);
596 if (tevent_req_nomem(subreq, req)) {
597 return;
599 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
602 static void get_complete_frag_got_rest(struct tevent_req *subreq)
604 struct tevent_req *req = tevent_req_callback_data(
605 subreq, struct tevent_req);
606 NTSTATUS status;
608 status = rpc_read_recv(subreq);
609 TALLOC_FREE(subreq);
610 if (!NT_STATUS_IS_OK(status)) {
611 tevent_req_nterror(req, status);
612 return;
614 tevent_req_done(req);
617 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
619 return tevent_req_simple_recv_ntstatus(req);
622 /****************************************************************************
623 NTLMSSP specific sign/seal.
624 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
625 In fact I should probably abstract these into identical pieces of code... JRA.
626 ****************************************************************************/
628 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
629 prs_struct *current_pdu,
630 uint8 *p_ss_padding_len)
632 RPC_HDR_AUTH auth_info;
633 uint32 save_offset = prs_offset(current_pdu);
634 uint32 auth_len = prhdr->auth_len;
635 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
636 unsigned char *data = NULL;
637 size_t data_len;
638 unsigned char *full_packet_data = NULL;
639 size_t full_packet_data_len;
640 DATA_BLOB auth_blob;
641 NTSTATUS status;
643 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
644 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
645 return NT_STATUS_OK;
648 if (!ntlmssp_state) {
649 return NT_STATUS_INVALID_PARAMETER;
652 /* Ensure there's enough data for an authenticated response. */
653 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
654 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
655 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
656 (unsigned int)auth_len ));
657 return NT_STATUS_BUFFER_TOO_SMALL;
661 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
662 * after the RPC header.
663 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
664 * functions as NTLMv2 checks the rpc headers also.
667 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
668 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
670 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
671 full_packet_data_len = prhdr->frag_len - auth_len;
673 /* Pull the auth header and the following data into a blob. */
674 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
675 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
676 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
677 return NT_STATUS_BUFFER_TOO_SMALL;
680 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
681 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
682 return NT_STATUS_BUFFER_TOO_SMALL;
685 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
686 auth_blob.length = auth_len;
688 switch (cli->auth->auth_level) {
689 case DCERPC_AUTH_LEVEL_PRIVACY:
690 /* Data is encrypted. */
691 status = ntlmssp_unseal_packet(ntlmssp_state,
692 data, data_len,
693 full_packet_data,
694 full_packet_data_len,
695 &auth_blob);
696 if (!NT_STATUS_IS_OK(status)) {
697 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
698 "packet from %s. Error was %s.\n",
699 rpccli_pipe_txt(talloc_tos(), cli),
700 nt_errstr(status) ));
701 return status;
703 break;
704 case DCERPC_AUTH_LEVEL_INTEGRITY:
705 /* Data is signed. */
706 status = ntlmssp_check_packet(ntlmssp_state,
707 data, data_len,
708 full_packet_data,
709 full_packet_data_len,
710 &auth_blob);
711 if (!NT_STATUS_IS_OK(status)) {
712 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
713 "packet from %s. Error was %s.\n",
714 rpccli_pipe_txt(talloc_tos(), cli),
715 nt_errstr(status) ));
716 return status;
718 break;
719 default:
720 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
721 "auth level %d\n", cli->auth->auth_level));
722 return NT_STATUS_INVALID_INFO_CLASS;
726 * Return the current pointer to the data offset.
729 if(!prs_set_offset(current_pdu, save_offset)) {
730 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
731 (unsigned int)save_offset ));
732 return NT_STATUS_BUFFER_TOO_SMALL;
736 * Remember the padding length. We must remove it from the real data
737 * stream once the sign/seal is done.
740 *p_ss_padding_len = auth_info.auth_pad_len;
742 return NT_STATUS_OK;
745 /****************************************************************************
746 schannel specific sign/seal.
747 ****************************************************************************/
749 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
750 prs_struct *current_pdu,
751 uint8 *p_ss_padding_len)
753 RPC_HDR_AUTH auth_info;
754 uint32 auth_len = prhdr->auth_len;
755 uint32 save_offset = prs_offset(current_pdu);
756 struct schannel_state *schannel_auth =
757 cli->auth->a_u.schannel_auth;
758 uint8_t *data;
759 uint32 data_len;
760 DATA_BLOB blob;
761 NTSTATUS status;
763 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
764 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
765 return NT_STATUS_OK;
768 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
769 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
770 return NT_STATUS_INVALID_PARAMETER;
773 if (!schannel_auth) {
774 return NT_STATUS_INVALID_PARAMETER;
777 /* Ensure there's enough data for an authenticated response. */
778 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
779 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
780 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
781 (unsigned int)auth_len ));
782 return NT_STATUS_INVALID_PARAMETER;
785 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
787 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
788 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
789 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
790 return NT_STATUS_BUFFER_TOO_SMALL;
793 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
794 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
795 return NT_STATUS_BUFFER_TOO_SMALL;
798 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
799 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
800 auth_info.auth_type));
801 return NT_STATUS_BUFFER_TOO_SMALL;
804 blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), auth_len);
806 if (DEBUGLEVEL >= 10) {
807 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
810 data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
812 switch (cli->auth->auth_level) {
813 case DCERPC_AUTH_LEVEL_PRIVACY:
814 status = netsec_incoming_packet(schannel_auth,
815 talloc_tos(),
816 true,
817 data,
818 data_len,
819 &blob);
820 break;
821 case DCERPC_AUTH_LEVEL_INTEGRITY:
822 status = netsec_incoming_packet(schannel_auth,
823 talloc_tos(),
824 false,
825 data,
826 data_len,
827 &blob);
828 break;
829 default:
830 status = NT_STATUS_INTERNAL_ERROR;
831 break;
834 if (!NT_STATUS_IS_OK(status)) {
835 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
836 "Connection to %s (%s).\n",
837 rpccli_pipe_txt(talloc_tos(), cli),
838 nt_errstr(status)));
839 return NT_STATUS_INVALID_PARAMETER;
843 * Return the current pointer to the data offset.
846 if(!prs_set_offset(current_pdu, save_offset)) {
847 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
848 (unsigned int)save_offset ));
849 return NT_STATUS_BUFFER_TOO_SMALL;
853 * Remember the padding length. We must remove it from the real data
854 * stream once the sign/seal is done.
857 *p_ss_padding_len = auth_info.auth_pad_len;
859 return NT_STATUS_OK;
862 /****************************************************************************
863 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
864 ****************************************************************************/
866 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
867 prs_struct *current_pdu,
868 uint8 *p_ss_padding_len)
870 NTSTATUS ret = NT_STATUS_OK;
872 /* Paranioa checks for auth_len. */
873 if (prhdr->auth_len) {
874 if (prhdr->auth_len > prhdr->frag_len) {
875 return NT_STATUS_INVALID_PARAMETER;
878 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
879 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
880 /* Integer wrap attempt. */
881 return NT_STATUS_INVALID_PARAMETER;
886 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
889 switch(cli->auth->auth_type) {
890 case PIPE_AUTH_TYPE_NONE:
891 if (prhdr->auth_len) {
892 DEBUG(3, ("cli_pipe_validate_rpc_response: "
893 "Connection to %s - got non-zero "
894 "auth len %u.\n",
895 rpccli_pipe_txt(talloc_tos(), cli),
896 (unsigned int)prhdr->auth_len ));
897 return NT_STATUS_INVALID_PARAMETER;
899 break;
901 case PIPE_AUTH_TYPE_NTLMSSP:
902 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
903 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
904 if (!NT_STATUS_IS_OK(ret)) {
905 return ret;
907 break;
909 case PIPE_AUTH_TYPE_SCHANNEL:
910 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
911 if (!NT_STATUS_IS_OK(ret)) {
912 return ret;
914 break;
916 case PIPE_AUTH_TYPE_KRB5:
917 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
918 default:
919 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
920 "to %s - unknown internal auth type %u.\n",
921 rpccli_pipe_txt(talloc_tos(), cli),
922 cli->auth->auth_type ));
923 return NT_STATUS_INVALID_INFO_CLASS;
926 return NT_STATUS_OK;
929 /****************************************************************************
930 Do basic authentication checks on an incoming pdu.
931 ****************************************************************************/
933 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
934 prs_struct *current_pdu,
935 uint8 expected_pkt_type,
936 char **ppdata,
937 uint32 *pdata_len,
938 prs_struct *return_data)
941 NTSTATUS ret = NT_STATUS_OK;
942 uint32 current_pdu_len = prs_data_size(current_pdu);
944 if (current_pdu_len != prhdr->frag_len) {
945 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
946 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
947 return NT_STATUS_INVALID_PARAMETER;
951 * Point the return values at the real data including the RPC
952 * header. Just in case the caller wants it.
954 *ppdata = prs_data_p(current_pdu);
955 *pdata_len = current_pdu_len;
957 /* Ensure we have the correct type. */
958 switch (prhdr->pkt_type) {
959 case DCERPC_PKT_ALTER_RESP:
960 case DCERPC_PKT_BIND_ACK:
962 /* Alter context and bind ack share the same packet definitions. */
963 break;
966 case DCERPC_PKT_RESPONSE:
968 RPC_HDR_RESP rhdr_resp;
969 uint8 ss_padding_len = 0;
971 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
972 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
973 return NT_STATUS_BUFFER_TOO_SMALL;
976 /* Here's where we deal with incoming sign/seal. */
977 ret = cli_pipe_validate_rpc_response(cli, prhdr,
978 current_pdu, &ss_padding_len);
979 if (!NT_STATUS_IS_OK(ret)) {
980 return ret;
983 /* Point the return values at the NDR data. Remember to remove any ss padding. */
984 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
986 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
987 return NT_STATUS_BUFFER_TOO_SMALL;
990 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
992 /* Remember to remove the auth footer. */
993 if (prhdr->auth_len) {
994 /* We've already done integer wrap tests on auth_len in
995 cli_pipe_validate_rpc_response(). */
996 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
997 return NT_STATUS_BUFFER_TOO_SMALL;
999 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
1002 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
1003 current_pdu_len, *pdata_len, ss_padding_len ));
1006 * If this is the first reply, and the allocation hint is reasonably, try and
1007 * set up the return_data parse_struct to the correct size.
1010 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
1011 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
1012 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
1013 "too large to allocate\n",
1014 (unsigned int)rhdr_resp.alloc_hint ));
1015 return NT_STATUS_NO_MEMORY;
1019 break;
1022 case DCERPC_PKT_BIND_NAK:
1023 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1024 "received from %s!\n",
1025 rpccli_pipe_txt(talloc_tos(), cli)));
1026 /* Use this for now... */
1027 return NT_STATUS_NETWORK_ACCESS_DENIED;
1029 case DCERPC_PKT_FAULT:
1031 RPC_HDR_RESP rhdr_resp;
1032 RPC_HDR_FAULT fault_resp;
1034 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1035 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1036 return NT_STATUS_BUFFER_TOO_SMALL;
1039 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
1040 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
1041 return NT_STATUS_BUFFER_TOO_SMALL;
1044 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1045 "code %s received from %s!\n",
1046 dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
1047 rpccli_pipe_txt(talloc_tos(), cli)));
1048 if (NT_STATUS_IS_OK(fault_resp.status)) {
1049 return NT_STATUS_UNSUCCESSFUL;
1050 } else {
1051 return fault_resp.status;
1055 default:
1056 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
1057 "from %s!\n",
1058 (unsigned int)prhdr->pkt_type,
1059 rpccli_pipe_txt(talloc_tos(), cli)));
1060 return NT_STATUS_INVALID_INFO_CLASS;
1063 if (prhdr->pkt_type != expected_pkt_type) {
1064 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1065 "got an unexpected RPC packet type - %u, not %u\n",
1066 rpccli_pipe_txt(talloc_tos(), cli),
1067 prhdr->pkt_type,
1068 expected_pkt_type));
1069 return NT_STATUS_INVALID_INFO_CLASS;
1072 /* Do this just before return - we don't want to modify any rpc header
1073 data before now as we may have needed to do cryptographic actions on
1074 it before. */
1076 if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) {
1077 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1078 "setting fragment first/last ON.\n"));
1079 prhdr->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST;
1082 return NT_STATUS_OK;
1085 /****************************************************************************
1086 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1087 Normally the frag_len and buffer size will match, but on the first trans
1088 reply there is a theoretical chance that buffer size > frag_len, so we must
1089 deal with that.
1090 ****************************************************************************/
1092 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
1094 uint32 current_pdu_len = prs_data_size(current_pdu);
1096 if (current_pdu_len < prhdr->frag_len) {
1097 return NT_STATUS_BUFFER_TOO_SMALL;
1100 /* Common case. */
1101 if (current_pdu_len == (uint32)prhdr->frag_len) {
1102 prs_mem_free(current_pdu);
1103 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1104 /* Make current_pdu dynamic with no memory. */
1105 prs_give_memory(current_pdu, 0, 0, True);
1106 return NT_STATUS_OK;
1110 * Oh no ! More data in buffer than we processed in current pdu.
1111 * Cheat. Move the data down and shrink the buffer.
1114 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1115 current_pdu_len - prhdr->frag_len);
1117 /* Remember to set the read offset back to zero. */
1118 prs_set_offset(current_pdu, 0);
1120 /* Shrink the buffer. */
1121 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1122 return NT_STATUS_BUFFER_TOO_SMALL;
1125 return NT_STATUS_OK;
1128 /****************************************************************************
1129 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1130 ****************************************************************************/
1132 struct cli_api_pipe_state {
1133 struct event_context *ev;
1134 struct rpc_cli_transport *transport;
1135 uint8_t *rdata;
1136 uint32_t rdata_len;
1139 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1140 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1141 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1143 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1144 struct event_context *ev,
1145 struct rpc_cli_transport *transport,
1146 uint8_t *data, size_t data_len,
1147 uint32_t max_rdata_len)
1149 struct tevent_req *req, *subreq;
1150 struct cli_api_pipe_state *state;
1151 NTSTATUS status;
1153 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1154 if (req == NULL) {
1155 return NULL;
1157 state->ev = ev;
1158 state->transport = transport;
1160 if (max_rdata_len < RPC_HEADER_LEN) {
1162 * For a RPC reply we always need at least RPC_HEADER_LEN
1163 * bytes. We check this here because we will receive
1164 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1166 status = NT_STATUS_INVALID_PARAMETER;
1167 goto post_status;
1170 if (transport->trans_send != NULL) {
1171 subreq = transport->trans_send(state, ev, data, data_len,
1172 max_rdata_len, transport->priv);
1173 if (subreq == NULL) {
1174 goto fail;
1176 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1177 return req;
1181 * If the transport does not provide a "trans" routine, i.e. for
1182 * example the ncacn_ip_tcp transport, do the write/read step here.
1185 subreq = rpc_write_send(state, ev, transport, data, data_len);
1186 if (subreq == NULL) {
1187 goto fail;
1189 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1190 return req;
1192 status = NT_STATUS_INVALID_PARAMETER;
1194 post_status:
1195 tevent_req_nterror(req, status);
1196 return tevent_req_post(req, ev);
1197 fail:
1198 TALLOC_FREE(req);
1199 return NULL;
1202 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1204 struct tevent_req *req = tevent_req_callback_data(
1205 subreq, struct tevent_req);
1206 struct cli_api_pipe_state *state = tevent_req_data(
1207 req, struct cli_api_pipe_state);
1208 NTSTATUS status;
1210 status = state->transport->trans_recv(subreq, state, &state->rdata,
1211 &state->rdata_len);
1212 TALLOC_FREE(subreq);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 tevent_req_nterror(req, status);
1215 return;
1217 tevent_req_done(req);
1220 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1222 struct tevent_req *req = tevent_req_callback_data(
1223 subreq, struct tevent_req);
1224 struct cli_api_pipe_state *state = tevent_req_data(
1225 req, struct cli_api_pipe_state);
1226 NTSTATUS status;
1228 status = rpc_write_recv(subreq);
1229 TALLOC_FREE(subreq);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 tevent_req_nterror(req, status);
1232 return;
1235 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1236 if (tevent_req_nomem(state->rdata, req)) {
1237 return;
1241 * We don't need to use rpc_read_send here, the upper layer will cope
1242 * with a short read, transport->trans_send could also return less
1243 * than state->max_rdata_len.
1245 subreq = state->transport->read_send(state, state->ev, state->rdata,
1246 RPC_HEADER_LEN,
1247 state->transport->priv);
1248 if (tevent_req_nomem(subreq, req)) {
1249 return;
1251 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1254 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1256 struct tevent_req *req = tevent_req_callback_data(
1257 subreq, struct tevent_req);
1258 struct cli_api_pipe_state *state = tevent_req_data(
1259 req, struct cli_api_pipe_state);
1260 NTSTATUS status;
1261 ssize_t received;
1263 status = state->transport->read_recv(subreq, &received);
1264 TALLOC_FREE(subreq);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 tevent_req_nterror(req, status);
1267 return;
1269 state->rdata_len = received;
1270 tevent_req_done(req);
1273 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1274 uint8_t **prdata, uint32_t *prdata_len)
1276 struct cli_api_pipe_state *state = tevent_req_data(
1277 req, struct cli_api_pipe_state);
1278 NTSTATUS status;
1280 if (tevent_req_is_nterror(req, &status)) {
1281 return status;
1284 *prdata = talloc_move(mem_ctx, &state->rdata);
1285 *prdata_len = state->rdata_len;
1286 return NT_STATUS_OK;
1289 /****************************************************************************
1290 Send data on an rpc pipe via trans. The prs_struct data must be the last
1291 pdu fragment of an NDR data stream.
1293 Receive response data from an rpc pipe, which may be large...
1295 Read the first fragment: unfortunately have to use SMBtrans for the first
1296 bit, then SMBreadX for subsequent bits.
1298 If first fragment received also wasn't the last fragment, continue
1299 getting fragments until we _do_ receive the last fragment.
1301 Request/Response PDU's look like the following...
1303 |<------------------PDU len----------------------------------------------->|
1304 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1306 +------------+-----------------+-------------+---------------+-------------+
1307 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1308 +------------+-----------------+-------------+---------------+-------------+
1310 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1311 signing & sealing being negotiated.
1313 ****************************************************************************/
1315 struct rpc_api_pipe_state {
1316 struct event_context *ev;
1317 struct rpc_pipe_client *cli;
1318 uint8_t expected_pkt_type;
1320 prs_struct incoming_frag;
1321 struct rpc_hdr_info rhdr;
1323 prs_struct incoming_pdu; /* Incoming reply */
1324 uint32_t incoming_pdu_offset;
1327 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1329 prs_mem_free(&state->incoming_frag);
1330 prs_mem_free(&state->incoming_pdu);
1331 return 0;
1334 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1335 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1337 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1338 struct event_context *ev,
1339 struct rpc_pipe_client *cli,
1340 prs_struct *data, /* Outgoing PDU */
1341 uint8_t expected_pkt_type)
1343 struct tevent_req *req, *subreq;
1344 struct rpc_api_pipe_state *state;
1345 uint16_t max_recv_frag;
1346 NTSTATUS status;
1348 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1349 if (req == NULL) {
1350 return NULL;
1352 state->ev = ev;
1353 state->cli = cli;
1354 state->expected_pkt_type = expected_pkt_type;
1355 state->incoming_pdu_offset = 0;
1357 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1359 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1360 /* Make incoming_pdu dynamic with no memory. */
1361 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1363 talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1366 * Ensure we're not sending too much.
1368 if (prs_offset(data) > cli->max_xmit_frag) {
1369 status = NT_STATUS_INVALID_PARAMETER;
1370 goto post_status;
1373 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1375 max_recv_frag = cli->max_recv_frag;
1377 #if 0
1378 max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1379 #endif
1381 subreq = cli_api_pipe_send(state, ev, cli->transport,
1382 (uint8_t *)prs_data_p(data),
1383 prs_offset(data), max_recv_frag);
1384 if (subreq == NULL) {
1385 goto fail;
1387 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1388 return req;
1390 post_status:
1391 tevent_req_nterror(req, status);
1392 return tevent_req_post(req, ev);
1393 fail:
1394 TALLOC_FREE(req);
1395 return NULL;
1398 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1400 struct tevent_req *req = tevent_req_callback_data(
1401 subreq, struct tevent_req);
1402 struct rpc_api_pipe_state *state = tevent_req_data(
1403 req, struct rpc_api_pipe_state);
1404 NTSTATUS status;
1405 uint8_t *rdata = NULL;
1406 uint32_t rdata_len = 0;
1407 char *rdata_copy;
1409 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1410 TALLOC_FREE(subreq);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1413 tevent_req_nterror(req, status);
1414 return;
1417 if (rdata == NULL) {
1418 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1419 rpccli_pipe_txt(talloc_tos(), state->cli)));
1420 tevent_req_done(req);
1421 return;
1425 * Give the memory received from cli_trans as dynamic to the current
1426 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1427 * :-(
1429 rdata_copy = (char *)memdup(rdata, rdata_len);
1430 TALLOC_FREE(rdata);
1431 if (tevent_req_nomem(rdata_copy, req)) {
1432 return;
1434 prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
1436 /* Ensure we have enough data for a pdu. */
1437 subreq = get_complete_frag_send(state, state->ev, state->cli,
1438 &state->rhdr, &state->incoming_frag);
1439 if (tevent_req_nomem(subreq, req)) {
1440 return;
1442 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1445 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1447 struct tevent_req *req = tevent_req_callback_data(
1448 subreq, struct tevent_req);
1449 struct rpc_api_pipe_state *state = tevent_req_data(
1450 req, struct rpc_api_pipe_state);
1451 NTSTATUS status;
1452 char *rdata = NULL;
1453 uint32_t rdata_len = 0;
1455 status = get_complete_frag_recv(subreq);
1456 TALLOC_FREE(subreq);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 DEBUG(5, ("get_complete_frag failed: %s\n",
1459 nt_errstr(status)));
1460 tevent_req_nterror(req, status);
1461 return;
1464 status = cli_pipe_validate_current_pdu(
1465 state->cli, &state->rhdr, &state->incoming_frag,
1466 state->expected_pkt_type, &rdata, &rdata_len,
1467 &state->incoming_pdu);
1469 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1470 (unsigned)prs_data_size(&state->incoming_frag),
1471 (unsigned)state->incoming_pdu_offset,
1472 nt_errstr(status)));
1474 if (!NT_STATUS_IS_OK(status)) {
1475 tevent_req_nterror(req, status);
1476 return;
1479 if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST)
1480 && (state->rhdr.pack_type[0] == 0)) {
1482 * Set the data type correctly for big-endian data on the
1483 * first packet.
1485 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1486 "big-endian.\n",
1487 rpccli_pipe_txt(talloc_tos(), state->cli)));
1488 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1491 * Check endianness on subsequent packets.
1493 if (state->incoming_frag.bigendian_data
1494 != state->incoming_pdu.bigendian_data) {
1495 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1496 "%s\n",
1497 state->incoming_pdu.bigendian_data?"big":"little",
1498 state->incoming_frag.bigendian_data?"big":"little"));
1499 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1500 return;
1503 /* Now copy the data portion out of the pdu into rbuf. */
1504 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1505 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1506 return;
1509 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1510 rdata, (size_t)rdata_len);
1511 state->incoming_pdu_offset += rdata_len;
1513 status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1514 &state->incoming_frag);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 tevent_req_nterror(req, status);
1517 return;
1520 if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
1521 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1522 rpccli_pipe_txt(talloc_tos(), state->cli),
1523 (unsigned)prs_data_size(&state->incoming_pdu)));
1524 tevent_req_done(req);
1525 return;
1528 subreq = get_complete_frag_send(state, state->ev, state->cli,
1529 &state->rhdr, &state->incoming_frag);
1530 if (tevent_req_nomem(subreq, req)) {
1531 return;
1533 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1536 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1537 prs_struct *reply_pdu)
1539 struct rpc_api_pipe_state *state = tevent_req_data(
1540 req, struct rpc_api_pipe_state);
1541 NTSTATUS status;
1543 if (tevent_req_is_nterror(req, &status)) {
1544 return status;
1547 *reply_pdu = state->incoming_pdu;
1548 reply_pdu->mem_ctx = mem_ctx;
1551 * Prevent state->incoming_pdu from being freed in
1552 * rpc_api_pipe_state_destructor()
1554 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1556 return NT_STATUS_OK;
1559 /*******************************************************************
1560 Creates krb5 auth bind.
1561 ********************************************************************/
1563 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1564 enum dcerpc_AuthLevel auth_level,
1565 RPC_HDR_AUTH *pauth_out,
1566 prs_struct *auth_data)
1568 #ifdef HAVE_KRB5
1569 int ret;
1570 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1571 DATA_BLOB tkt = data_blob_null;
1572 DATA_BLOB tkt_wrapped = data_blob_null;
1574 /* We may change the pad length before marshalling. */
1575 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
1577 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1578 a->service_principal ));
1580 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1582 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1583 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1585 if (ret) {
1586 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1587 "failed with %s\n",
1588 a->service_principal,
1589 error_message(ret) ));
1591 data_blob_free(&tkt);
1592 prs_mem_free(auth_data);
1593 return NT_STATUS_INVALID_PARAMETER;
1596 /* wrap that up in a nice GSS-API wrapping */
1597 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1599 data_blob_free(&tkt);
1601 /* Auth len in the rpc header doesn't include auth_header. */
1602 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1603 data_blob_free(&tkt_wrapped);
1604 prs_mem_free(auth_data);
1605 return NT_STATUS_NO_MEMORY;
1608 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1609 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1611 data_blob_free(&tkt_wrapped);
1612 return NT_STATUS_OK;
1613 #else
1614 return NT_STATUS_INVALID_PARAMETER;
1615 #endif
1618 /*******************************************************************
1619 Creates SPNEGO NTLMSSP auth bind.
1620 ********************************************************************/
1622 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1623 enum dcerpc_AuthLevel auth_level,
1624 RPC_HDR_AUTH *pauth_out,
1625 prs_struct *auth_data)
1627 NTSTATUS nt_status;
1628 DATA_BLOB null_blob = data_blob_null;
1629 DATA_BLOB request = data_blob_null;
1630 DATA_BLOB spnego_msg = data_blob_null;
1632 /* We may change the pad length before marshalling. */
1633 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
1635 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1636 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1637 null_blob,
1638 &request);
1640 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1641 data_blob_free(&request);
1642 prs_mem_free(auth_data);
1643 return nt_status;
1646 /* Wrap this in SPNEGO. */
1647 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1649 data_blob_free(&request);
1651 /* Auth len in the rpc header doesn't include auth_header. */
1652 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1653 data_blob_free(&spnego_msg);
1654 prs_mem_free(auth_data);
1655 return NT_STATUS_NO_MEMORY;
1658 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1659 dump_data(5, spnego_msg.data, spnego_msg.length);
1661 data_blob_free(&spnego_msg);
1662 return NT_STATUS_OK;
1665 /*******************************************************************
1666 Creates NTLMSSP auth bind.
1667 ********************************************************************/
1669 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1670 enum dcerpc_AuthLevel auth_level,
1671 RPC_HDR_AUTH *pauth_out,
1672 prs_struct *auth_data)
1674 NTSTATUS nt_status;
1675 DATA_BLOB null_blob = data_blob_null;
1676 DATA_BLOB request = data_blob_null;
1678 /* We may change the pad length before marshalling. */
1679 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
1681 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1682 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1683 null_blob,
1684 &request);
1686 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1687 data_blob_free(&request);
1688 prs_mem_free(auth_data);
1689 return nt_status;
1692 /* Auth len in the rpc header doesn't include auth_header. */
1693 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1694 data_blob_free(&request);
1695 prs_mem_free(auth_data);
1696 return NT_STATUS_NO_MEMORY;
1699 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1700 dump_data(5, request.data, request.length);
1702 data_blob_free(&request);
1703 return NT_STATUS_OK;
1706 /*******************************************************************
1707 Creates schannel auth bind.
1708 ********************************************************************/
1710 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1711 enum dcerpc_AuthLevel auth_level,
1712 RPC_HDR_AUTH *pauth_out,
1713 prs_struct *auth_data)
1715 struct NL_AUTH_MESSAGE r;
1716 enum ndr_err_code ndr_err;
1717 DATA_BLOB blob;
1719 /* We may change the pad length before marshalling. */
1720 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
1722 /* Use lp_workgroup() if domain not specified */
1724 if (!cli->auth->domain || !cli->auth->domain[0]) {
1725 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1726 if (cli->auth->domain == NULL) {
1727 return NT_STATUS_NO_MEMORY;
1732 * Now marshall the data into the auth parse_struct.
1735 r.MessageType = NL_NEGOTIATE_REQUEST;
1736 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1737 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1738 r.oem_netbios_domain.a = cli->auth->domain;
1739 r.oem_netbios_computer.a = global_myname();
1741 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &r,
1742 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
1743 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1744 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1745 prs_mem_free(auth_data);
1746 return ndr_map_error2ntstatus(ndr_err);
1749 if (DEBUGLEVEL >= 10) {
1750 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
1753 if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
1755 prs_mem_free(auth_data);
1756 return NT_STATUS_NO_MEMORY;
1759 return NT_STATUS_OK;
1762 /*******************************************************************
1763 Creates the internals of a DCE/RPC bind request or alter context PDU.
1764 ********************************************************************/
1766 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type,
1767 prs_struct *rpc_out,
1768 uint32 rpc_call_id,
1769 const struct ndr_syntax_id *abstract,
1770 const struct ndr_syntax_id *transfer,
1771 RPC_HDR_AUTH *phdr_auth,
1772 prs_struct *pauth_info)
1774 RPC_HDR hdr;
1775 RPC_HDR_RB hdr_rb;
1776 RPC_CONTEXT rpc_ctx;
1777 uint16 auth_len = prs_offset(pauth_info);
1778 uint8 ss_padding_len = 0;
1779 uint16 frag_len = 0;
1781 /* create the RPC context. */
1782 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1784 /* create the bind request RPC_HDR_RB */
1785 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1787 /* Start building the frag length. */
1788 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1790 /* Do we need to pad ? */
1791 if (auth_len) {
1792 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1793 if (data_len % 8) {
1794 ss_padding_len = 8 - (data_len % 8);
1795 phdr_auth->auth_pad_len = ss_padding_len;
1797 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1800 /* Create the request RPC_HDR */
1801 init_rpc_hdr(&hdr, pkt_type, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id, frag_len, auth_len);
1803 /* Marshall the RPC header */
1804 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1805 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1806 return NT_STATUS_NO_MEMORY;
1809 /* Marshall the bind request data */
1810 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1811 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1812 return NT_STATUS_NO_MEMORY;
1816 * Grow the outgoing buffer to store any auth info.
1819 if(auth_len != 0) {
1820 if (ss_padding_len) {
1821 char pad[8];
1822 memset(pad, '\0', 8);
1823 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1824 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1825 return NT_STATUS_NO_MEMORY;
1829 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1830 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1831 return NT_STATUS_NO_MEMORY;
1835 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1836 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1837 return NT_STATUS_NO_MEMORY;
1841 return NT_STATUS_OK;
1844 /*******************************************************************
1845 Creates a DCE/RPC bind request.
1846 ********************************************************************/
1848 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1849 prs_struct *rpc_out,
1850 uint32 rpc_call_id,
1851 const struct ndr_syntax_id *abstract,
1852 const struct ndr_syntax_id *transfer,
1853 enum pipe_auth_type auth_type,
1854 enum dcerpc_AuthLevel auth_level)
1856 RPC_HDR_AUTH hdr_auth;
1857 prs_struct auth_info;
1858 NTSTATUS ret = NT_STATUS_OK;
1860 ZERO_STRUCT(hdr_auth);
1861 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1862 return NT_STATUS_NO_MEMORY;
1864 switch (auth_type) {
1865 case PIPE_AUTH_TYPE_SCHANNEL:
1866 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1867 if (!NT_STATUS_IS_OK(ret)) {
1868 prs_mem_free(&auth_info);
1869 return ret;
1871 break;
1873 case PIPE_AUTH_TYPE_NTLMSSP:
1874 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1875 if (!NT_STATUS_IS_OK(ret)) {
1876 prs_mem_free(&auth_info);
1877 return ret;
1879 break;
1881 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1882 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1883 if (!NT_STATUS_IS_OK(ret)) {
1884 prs_mem_free(&auth_info);
1885 return ret;
1887 break;
1889 case PIPE_AUTH_TYPE_KRB5:
1890 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1891 if (!NT_STATUS_IS_OK(ret)) {
1892 prs_mem_free(&auth_info);
1893 return ret;
1895 break;
1897 case PIPE_AUTH_TYPE_NONE:
1898 break;
1900 default:
1901 /* "Can't" happen. */
1902 return NT_STATUS_INVALID_INFO_CLASS;
1905 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1906 rpc_out,
1907 rpc_call_id,
1908 abstract,
1909 transfer,
1910 &hdr_auth,
1911 &auth_info);
1913 prs_mem_free(&auth_info);
1914 return ret;
1917 /*******************************************************************
1918 Create and add the NTLMSSP sign/seal auth header and data.
1919 ********************************************************************/
1921 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1922 RPC_HDR *phdr,
1923 uint32 ss_padding_len,
1924 prs_struct *outgoing_pdu)
1926 RPC_HDR_AUTH auth_info;
1927 NTSTATUS status;
1928 DATA_BLOB auth_blob = data_blob_null;
1929 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1931 if (!cli->auth->a_u.ntlmssp_state) {
1932 return NT_STATUS_INVALID_PARAMETER;
1935 /* Init and marshall the auth header. */
1936 init_rpc_hdr_auth(&auth_info,
1937 map_pipe_auth_type_to_rpc_auth_type(
1938 cli->auth->auth_type),
1939 cli->auth->auth_level,
1940 ss_padding_len,
1941 1 /* context id. */);
1943 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1944 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1945 data_blob_free(&auth_blob);
1946 return NT_STATUS_NO_MEMORY;
1949 switch (cli->auth->auth_level) {
1950 case DCERPC_AUTH_LEVEL_PRIVACY:
1951 /* Data portion is encrypted. */
1952 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1953 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1954 data_and_pad_len,
1955 (unsigned char *)prs_data_p(outgoing_pdu),
1956 (size_t)prs_offset(outgoing_pdu),
1957 &auth_blob);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 data_blob_free(&auth_blob);
1960 return status;
1962 break;
1964 case DCERPC_AUTH_LEVEL_INTEGRITY:
1965 /* Data is signed. */
1966 status = ntlmssp_sign_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 default:
1979 /* Can't happen. */
1980 smb_panic("bad auth level");
1981 /* Notreached. */
1982 return NT_STATUS_INVALID_PARAMETER;
1985 /* Finally marshall the blob. */
1987 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1988 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1989 (unsigned int)NTLMSSP_SIG_SIZE));
1990 data_blob_free(&auth_blob);
1991 return NT_STATUS_NO_MEMORY;
1994 data_blob_free(&auth_blob);
1995 return NT_STATUS_OK;
1998 /*******************************************************************
1999 Create and add the schannel sign/seal auth header and data.
2000 ********************************************************************/
2002 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2003 RPC_HDR *phdr,
2004 uint32 ss_padding_len,
2005 prs_struct *outgoing_pdu)
2007 RPC_HDR_AUTH auth_info;
2008 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2009 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2010 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2011 DATA_BLOB blob;
2012 NTSTATUS status;
2014 if (!sas) {
2015 return NT_STATUS_INVALID_PARAMETER;
2018 /* Init and marshall the auth header. */
2019 init_rpc_hdr_auth(&auth_info,
2020 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2021 cli->auth->auth_level,
2022 ss_padding_len,
2023 1 /* context id. */);
2025 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
2026 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
2027 return NT_STATUS_NO_MEMORY;
2030 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2031 sas->seq_num));
2033 switch (cli->auth->auth_level) {
2034 case DCERPC_AUTH_LEVEL_PRIVACY:
2035 status = netsec_outgoing_packet(sas,
2036 talloc_tos(),
2037 true,
2038 (uint8_t *)data_p,
2039 data_and_pad_len,
2040 &blob);
2041 break;
2042 case DCERPC_AUTH_LEVEL_INTEGRITY:
2043 status = netsec_outgoing_packet(sas,
2044 talloc_tos(),
2045 false,
2046 (uint8_t *)data_p,
2047 data_and_pad_len,
2048 &blob);
2049 break;
2050 default:
2051 status = NT_STATUS_INTERNAL_ERROR;
2052 break;
2055 if (!NT_STATUS_IS_OK(status)) {
2056 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2057 nt_errstr(status)));
2058 return status;
2061 if (DEBUGLEVEL >= 10) {
2062 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2065 /* Finally marshall the blob. */
2066 if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
2067 return NT_STATUS_NO_MEMORY;
2070 return NT_STATUS_OK;
2073 /*******************************************************************
2074 Calculate how much data we're going to send in this packet, also
2075 work out any sign/seal padding length.
2076 ********************************************************************/
2078 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2079 uint32 data_left,
2080 uint16 *p_frag_len,
2081 uint16 *p_auth_len,
2082 uint32 *p_ss_padding)
2084 uint32 data_space, data_len;
2086 #if 0
2087 if ((data_left > 0) && (sys_random() % 2)) {
2088 data_left = MAX(data_left/2, 1);
2090 #endif
2092 switch (cli->auth->auth_level) {
2093 case DCERPC_AUTH_LEVEL_NONE:
2094 case DCERPC_AUTH_LEVEL_CONNECT:
2095 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2096 data_len = MIN(data_space, data_left);
2097 *p_ss_padding = 0;
2098 *p_auth_len = 0;
2099 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2100 return data_len;
2102 case DCERPC_AUTH_LEVEL_INTEGRITY:
2103 case DCERPC_AUTH_LEVEL_PRIVACY:
2104 /* Treat the same for all authenticated rpc requests. */
2105 switch(cli->auth->auth_type) {
2106 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2107 case PIPE_AUTH_TYPE_NTLMSSP:
2108 *p_auth_len = NTLMSSP_SIG_SIZE;
2109 break;
2110 case PIPE_AUTH_TYPE_SCHANNEL:
2111 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2112 break;
2113 default:
2114 smb_panic("bad auth type");
2115 break;
2118 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2119 RPC_HDR_AUTH_LEN - *p_auth_len;
2121 data_len = MIN(data_space, data_left);
2122 *p_ss_padding = 0;
2123 if (data_len % 8) {
2124 *p_ss_padding = 8 - (data_len % 8);
2126 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
2127 data_len + *p_ss_padding + /* data plus padding. */
2128 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
2129 return data_len;
2131 default:
2132 smb_panic("bad auth level");
2133 /* Notreached. */
2134 return 0;
2138 /*******************************************************************
2139 External interface.
2140 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2141 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2142 and deals with signing/sealing details.
2143 ********************************************************************/
2145 struct rpc_api_pipe_req_state {
2146 struct event_context *ev;
2147 struct rpc_pipe_client *cli;
2148 uint8_t op_num;
2149 uint32_t call_id;
2150 prs_struct *req_data;
2151 uint32_t req_data_sent;
2152 prs_struct outgoing_frag;
2153 prs_struct reply_pdu;
2156 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2158 prs_mem_free(&s->outgoing_frag);
2159 prs_mem_free(&s->reply_pdu);
2160 return 0;
2163 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2164 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2165 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2166 bool *is_last_frag);
2168 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2169 struct event_context *ev,
2170 struct rpc_pipe_client *cli,
2171 uint8_t op_num,
2172 prs_struct *req_data)
2174 struct tevent_req *req, *subreq;
2175 struct rpc_api_pipe_req_state *state;
2176 NTSTATUS status;
2177 bool is_last_frag;
2179 req = tevent_req_create(mem_ctx, &state,
2180 struct rpc_api_pipe_req_state);
2181 if (req == NULL) {
2182 return NULL;
2184 state->ev = ev;
2185 state->cli = cli;
2186 state->op_num = op_num;
2187 state->req_data = req_data;
2188 state->req_data_sent = 0;
2189 state->call_id = get_rpc_call_id();
2191 if (cli->max_xmit_frag
2192 < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2193 /* Server is screwed up ! */
2194 status = NT_STATUS_INVALID_PARAMETER;
2195 goto post_status;
2198 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2200 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2201 state, MARSHALL)) {
2202 goto fail;
2205 talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2207 status = prepare_next_frag(state, &is_last_frag);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 goto post_status;
2212 if (is_last_frag) {
2213 subreq = rpc_api_pipe_send(state, ev, state->cli,
2214 &state->outgoing_frag,
2215 DCERPC_PKT_RESPONSE);
2216 if (subreq == NULL) {
2217 goto fail;
2219 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2220 } else {
2221 subreq = rpc_write_send(
2222 state, ev, cli->transport,
2223 (uint8_t *)prs_data_p(&state->outgoing_frag),
2224 prs_offset(&state->outgoing_frag));
2225 if (subreq == NULL) {
2226 goto fail;
2228 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2229 req);
2231 return req;
2233 post_status:
2234 tevent_req_nterror(req, status);
2235 return tevent_req_post(req, ev);
2236 fail:
2237 TALLOC_FREE(req);
2238 return NULL;
2241 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2242 bool *is_last_frag)
2244 RPC_HDR hdr;
2245 RPC_HDR_REQ hdr_req;
2246 uint32_t data_sent_thistime;
2247 uint16_t auth_len;
2248 uint16_t frag_len;
2249 uint8_t flags = 0;
2250 uint32_t ss_padding;
2251 uint32_t data_left;
2252 char pad[8] = { 0, };
2253 NTSTATUS status;
2255 data_left = prs_offset(state->req_data) - state->req_data_sent;
2257 data_sent_thistime = calculate_data_len_tosend(
2258 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2260 if (state->req_data_sent == 0) {
2261 flags = DCERPC_PFC_FLAG_FIRST;
2264 if (data_sent_thistime == data_left) {
2265 flags |= DCERPC_PFC_FLAG_LAST;
2268 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2269 return NT_STATUS_NO_MEMORY;
2272 /* Create and marshall the header and request header. */
2273 init_rpc_hdr(&hdr, DCERPC_PKT_REQUEST, flags, state->call_id, frag_len,
2274 auth_len);
2276 if (!smb_io_rpc_hdr("hdr ", &hdr, &state->outgoing_frag, 0)) {
2277 return NT_STATUS_NO_MEMORY;
2280 /* Create the rpc request RPC_HDR_REQ */
2281 init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2282 state->op_num);
2284 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2285 &state->outgoing_frag, 0)) {
2286 return NT_STATUS_NO_MEMORY;
2289 /* Copy in the data, plus any ss padding. */
2290 if (!prs_append_some_prs_data(&state->outgoing_frag,
2291 state->req_data, state->req_data_sent,
2292 data_sent_thistime)) {
2293 return NT_STATUS_NO_MEMORY;
2296 /* Copy the sign/seal padding data. */
2297 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2298 return NT_STATUS_NO_MEMORY;
2301 /* Generate any auth sign/seal and add the auth footer. */
2302 switch (state->cli->auth->auth_type) {
2303 case PIPE_AUTH_TYPE_NONE:
2304 status = NT_STATUS_OK;
2305 break;
2306 case PIPE_AUTH_TYPE_NTLMSSP:
2307 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2308 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2309 &state->outgoing_frag);
2310 break;
2311 case PIPE_AUTH_TYPE_SCHANNEL:
2312 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2313 &state->outgoing_frag);
2314 break;
2315 default:
2316 status = NT_STATUS_INVALID_PARAMETER;
2317 break;
2320 state->req_data_sent += data_sent_thistime;
2321 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2323 return status;
2326 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2328 struct tevent_req *req = tevent_req_callback_data(
2329 subreq, struct tevent_req);
2330 struct rpc_api_pipe_req_state *state = tevent_req_data(
2331 req, struct rpc_api_pipe_req_state);
2332 NTSTATUS status;
2333 bool is_last_frag;
2335 status = rpc_write_recv(subreq);
2336 TALLOC_FREE(subreq);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 tevent_req_nterror(req, status);
2339 return;
2342 status = prepare_next_frag(state, &is_last_frag);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 tevent_req_nterror(req, status);
2345 return;
2348 if (is_last_frag) {
2349 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2350 &state->outgoing_frag,
2351 DCERPC_PKT_RESPONSE);
2352 if (tevent_req_nomem(subreq, req)) {
2353 return;
2355 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2356 } else {
2357 subreq = rpc_write_send(
2358 state, state->ev,
2359 state->cli->transport,
2360 (uint8_t *)prs_data_p(&state->outgoing_frag),
2361 prs_offset(&state->outgoing_frag));
2362 if (tevent_req_nomem(subreq, req)) {
2363 return;
2365 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2366 req);
2370 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2372 struct tevent_req *req = tevent_req_callback_data(
2373 subreq, struct tevent_req);
2374 struct rpc_api_pipe_req_state *state = tevent_req_data(
2375 req, struct rpc_api_pipe_req_state);
2376 NTSTATUS status;
2378 status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2379 TALLOC_FREE(subreq);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 tevent_req_nterror(req, status);
2382 return;
2384 tevent_req_done(req);
2387 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2388 prs_struct *reply_pdu)
2390 struct rpc_api_pipe_req_state *state = tevent_req_data(
2391 req, struct rpc_api_pipe_req_state);
2392 NTSTATUS status;
2394 if (tevent_req_is_nterror(req, &status)) {
2396 * We always have to initialize to reply pdu, even if there is
2397 * none. The rpccli_* caller routines expect this.
2399 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2400 return status;
2403 *reply_pdu = state->reply_pdu;
2404 reply_pdu->mem_ctx = mem_ctx;
2407 * Prevent state->req_pdu from being freed in
2408 * rpc_api_pipe_req_state_destructor()
2410 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2412 return NT_STATUS_OK;
2415 #if 0
2416 /****************************************************************************
2417 Set the handle state.
2418 ****************************************************************************/
2420 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2421 const char *pipe_name, uint16 device_state)
2423 bool state_set = False;
2424 char param[2];
2425 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2426 char *rparam = NULL;
2427 char *rdata = NULL;
2428 uint32 rparam_len, rdata_len;
2430 if (pipe_name == NULL)
2431 return False;
2433 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2434 cli->fnum, pipe_name, device_state));
2436 /* create parameters: device state */
2437 SSVAL(param, 0, device_state);
2439 /* create setup parameters. */
2440 setup[0] = 0x0001;
2441 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2443 /* send the data on \PIPE\ */
2444 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2445 setup, 2, 0, /* setup, length, max */
2446 param, 2, 0, /* param, length, max */
2447 NULL, 0, 1024, /* data, length, max */
2448 &rparam, &rparam_len, /* return param, length */
2449 &rdata, &rdata_len)) /* return data, length */
2451 DEBUG(5, ("Set Handle state: return OK\n"));
2452 state_set = True;
2455 SAFE_FREE(rparam);
2456 SAFE_FREE(rdata);
2458 return state_set;
2460 #endif
2462 /****************************************************************************
2463 Check the rpc bind acknowledge response.
2464 ****************************************************************************/
2466 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2467 const struct ndr_syntax_id *transfer)
2469 if ( hdr_ba->addr.len == 0) {
2470 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2473 /* check the transfer syntax */
2474 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2475 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2476 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2477 return False;
2480 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2481 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2482 hdr_ba->res.num_results, hdr_ba->res.reason));
2485 DEBUG(5,("check_bind_response: accepted!\n"));
2486 return True;
2489 /*******************************************************************
2490 Creates a DCE/RPC bind authentication response.
2491 This is the packet that is sent back to the server once we
2492 have received a BIND-ACK, to finish the third leg of
2493 the authentication handshake.
2494 ********************************************************************/
2496 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2497 uint32 rpc_call_id,
2498 enum pipe_auth_type auth_type,
2499 enum dcerpc_AuthLevel auth_level,
2500 DATA_BLOB *pauth_blob,
2501 prs_struct *rpc_out)
2503 RPC_HDR hdr;
2504 RPC_HDR_AUTH hdr_auth;
2505 uint32 pad = 0;
2507 /* Create the request RPC_HDR */
2508 init_rpc_hdr(&hdr, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id,
2509 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2510 pauth_blob->length );
2512 /* Marshall it. */
2513 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2514 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2515 return NT_STATUS_NO_MEMORY;
2519 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2520 about padding - shouldn't this pad to length 8 ? JRA.
2523 /* 4 bytes padding. */
2524 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2525 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2526 return NT_STATUS_NO_MEMORY;
2529 /* Create the request RPC_HDR_AUTHA */
2530 init_rpc_hdr_auth(&hdr_auth,
2531 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2532 auth_level, 0, 1);
2534 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2535 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2536 return NT_STATUS_NO_MEMORY;
2540 * Append the auth data to the outgoing buffer.
2543 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2544 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2545 return NT_STATUS_NO_MEMORY;
2548 return NT_STATUS_OK;
2551 /*******************************************************************
2552 Creates a DCE/RPC bind alter context authentication request which
2553 may contain a spnego auth blobl
2554 ********************************************************************/
2556 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2557 const struct ndr_syntax_id *abstract,
2558 const struct ndr_syntax_id *transfer,
2559 enum dcerpc_AuthLevel auth_level,
2560 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2561 prs_struct *rpc_out)
2563 RPC_HDR_AUTH hdr_auth;
2564 prs_struct auth_info;
2565 NTSTATUS ret = NT_STATUS_OK;
2567 ZERO_STRUCT(hdr_auth);
2568 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2569 return NT_STATUS_NO_MEMORY;
2571 /* We may change the pad length before marshalling. */
2572 init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
2574 if (pauth_blob->length) {
2575 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2576 prs_mem_free(&auth_info);
2577 return NT_STATUS_NO_MEMORY;
2581 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2582 rpc_out,
2583 rpc_call_id,
2584 abstract,
2585 transfer,
2586 &hdr_auth,
2587 &auth_info);
2588 prs_mem_free(&auth_info);
2589 return ret;
2592 /****************************************************************************
2593 Do an rpc bind.
2594 ****************************************************************************/
2596 struct rpc_pipe_bind_state {
2597 struct event_context *ev;
2598 struct rpc_pipe_client *cli;
2599 prs_struct rpc_out;
2600 uint32_t rpc_call_id;
2603 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2605 prs_mem_free(&state->rpc_out);
2606 return 0;
2609 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2610 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2611 struct rpc_pipe_bind_state *state,
2612 struct rpc_hdr_info *phdr,
2613 prs_struct *reply_pdu);
2614 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2615 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2616 struct rpc_pipe_bind_state *state,
2617 struct rpc_hdr_info *phdr,
2618 prs_struct *reply_pdu);
2619 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2621 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2622 struct event_context *ev,
2623 struct rpc_pipe_client *cli,
2624 struct cli_pipe_auth_data *auth)
2626 struct tevent_req *req, *subreq;
2627 struct rpc_pipe_bind_state *state;
2628 NTSTATUS status;
2630 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2631 if (req == NULL) {
2632 return NULL;
2635 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2636 rpccli_pipe_txt(talloc_tos(), cli),
2637 (unsigned int)auth->auth_type,
2638 (unsigned int)auth->auth_level ));
2640 state->ev = ev;
2641 state->cli = cli;
2642 state->rpc_call_id = get_rpc_call_id();
2644 prs_init_empty(&state->rpc_out, state, MARSHALL);
2645 talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2647 cli->auth = talloc_move(cli, &auth);
2649 /* Marshall the outgoing data. */
2650 status = create_rpc_bind_req(cli, &state->rpc_out,
2651 state->rpc_call_id,
2652 &cli->abstract_syntax,
2653 &cli->transfer_syntax,
2654 cli->auth->auth_type,
2655 cli->auth->auth_level);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto post_status;
2661 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2662 DCERPC_PKT_BIND_ACK);
2663 if (subreq == NULL) {
2664 goto fail;
2666 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2667 return req;
2669 post_status:
2670 tevent_req_nterror(req, status);
2671 return tevent_req_post(req, ev);
2672 fail:
2673 TALLOC_FREE(req);
2674 return NULL;
2677 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2679 struct tevent_req *req = tevent_req_callback_data(
2680 subreq, struct tevent_req);
2681 struct rpc_pipe_bind_state *state = tevent_req_data(
2682 req, struct rpc_pipe_bind_state);
2683 prs_struct reply_pdu;
2684 struct rpc_hdr_info hdr;
2685 struct rpc_hdr_ba_info hdr_ba;
2686 NTSTATUS status;
2688 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2689 TALLOC_FREE(subreq);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2692 rpccli_pipe_txt(talloc_tos(), state->cli),
2693 nt_errstr(status)));
2694 tevent_req_nterror(req, status);
2695 return;
2698 /* Unmarshall the RPC header */
2699 if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2700 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2701 prs_mem_free(&reply_pdu);
2702 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2703 return;
2706 if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2707 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2708 "RPC_HDR_BA.\n"));
2709 prs_mem_free(&reply_pdu);
2710 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2711 return;
2714 if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2715 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2716 prs_mem_free(&reply_pdu);
2717 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2718 return;
2721 state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2722 state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2725 * For authenticated binds we may need to do 3 or 4 leg binds.
2728 switch(state->cli->auth->auth_type) {
2730 case PIPE_AUTH_TYPE_NONE:
2731 case PIPE_AUTH_TYPE_SCHANNEL:
2732 /* Bind complete. */
2733 prs_mem_free(&reply_pdu);
2734 tevent_req_done(req);
2735 break;
2737 case PIPE_AUTH_TYPE_NTLMSSP:
2738 /* Need to send AUTH3 packet - no reply. */
2739 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2740 &reply_pdu);
2741 prs_mem_free(&reply_pdu);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 tevent_req_nterror(req, status);
2745 break;
2747 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2748 /* Need to send alter context request and reply. */
2749 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2750 &reply_pdu);
2751 prs_mem_free(&reply_pdu);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 tevent_req_nterror(req, status);
2755 break;
2757 case PIPE_AUTH_TYPE_KRB5:
2758 /* */
2760 default:
2761 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2762 (unsigned int)state->cli->auth->auth_type));
2763 prs_mem_free(&reply_pdu);
2764 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2768 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2769 struct rpc_pipe_bind_state *state,
2770 struct rpc_hdr_info *phdr,
2771 prs_struct *reply_pdu)
2773 DATA_BLOB server_response = data_blob_null;
2774 DATA_BLOB client_reply = data_blob_null;
2775 struct rpc_hdr_auth_info hdr_auth;
2776 struct tevent_req *subreq;
2777 NTSTATUS status;
2779 if ((phdr->auth_len == 0)
2780 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2781 return NT_STATUS_INVALID_PARAMETER;
2784 if (!prs_set_offset(
2785 reply_pdu,
2786 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2787 return NT_STATUS_INVALID_PARAMETER;
2790 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2791 return NT_STATUS_INVALID_PARAMETER;
2794 /* TODO - check auth_type/auth_level match. */
2796 server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2797 prs_copy_data_out((char *)server_response.data, reply_pdu,
2798 phdr->auth_len);
2800 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2801 server_response, &client_reply);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2805 "blob failed: %s.\n", nt_errstr(status)));
2806 return status;
2809 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2811 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2812 state->cli->auth->auth_type,
2813 state->cli->auth->auth_level,
2814 &client_reply, &state->rpc_out);
2815 data_blob_free(&client_reply);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 return status;
2821 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2822 (uint8_t *)prs_data_p(&state->rpc_out),
2823 prs_offset(&state->rpc_out));
2824 if (subreq == NULL) {
2825 return NT_STATUS_NO_MEMORY;
2827 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2828 return NT_STATUS_OK;
2831 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2833 struct tevent_req *req = tevent_req_callback_data(
2834 subreq, struct tevent_req);
2835 NTSTATUS status;
2837 status = rpc_write_recv(subreq);
2838 TALLOC_FREE(subreq);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 tevent_req_nterror(req, status);
2841 return;
2843 tevent_req_done(req);
2846 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2847 struct rpc_pipe_bind_state *state,
2848 struct rpc_hdr_info *phdr,
2849 prs_struct *reply_pdu)
2851 DATA_BLOB server_spnego_response = data_blob_null;
2852 DATA_BLOB server_ntlm_response = data_blob_null;
2853 DATA_BLOB client_reply = data_blob_null;
2854 DATA_BLOB tmp_blob = data_blob_null;
2855 RPC_HDR_AUTH hdr_auth;
2856 struct tevent_req *subreq;
2857 NTSTATUS status;
2859 if ((phdr->auth_len == 0)
2860 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2861 return NT_STATUS_INVALID_PARAMETER;
2864 /* Process the returned NTLMSSP blob first. */
2865 if (!prs_set_offset(
2866 reply_pdu,
2867 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2868 return NT_STATUS_INVALID_PARAMETER;
2871 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2872 return NT_STATUS_INVALID_PARAMETER;
2875 server_spnego_response = data_blob(NULL, phdr->auth_len);
2876 prs_copy_data_out((char *)server_spnego_response.data,
2877 reply_pdu, phdr->auth_len);
2880 * The server might give us back two challenges - tmp_blob is for the
2881 * second.
2883 if (!spnego_parse_challenge(server_spnego_response,
2884 &server_ntlm_response, &tmp_blob)) {
2885 data_blob_free(&server_spnego_response);
2886 data_blob_free(&server_ntlm_response);
2887 data_blob_free(&tmp_blob);
2888 return NT_STATUS_INVALID_PARAMETER;
2891 /* We're finished with the server spnego response and the tmp_blob. */
2892 data_blob_free(&server_spnego_response);
2893 data_blob_free(&tmp_blob);
2895 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2896 server_ntlm_response, &client_reply);
2898 /* Finished with the server_ntlm response */
2899 data_blob_free(&server_ntlm_response);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2903 "using server blob failed.\n"));
2904 data_blob_free(&client_reply);
2905 return status;
2908 /* SPNEGO wrap the client reply. */
2909 tmp_blob = spnego_gen_auth(client_reply);
2910 data_blob_free(&client_reply);
2911 client_reply = tmp_blob;
2912 tmp_blob = data_blob_null;
2914 /* Now prepare the alter context pdu. */
2915 prs_init_empty(&state->rpc_out, state, MARSHALL);
2917 status = create_rpc_alter_context(state->rpc_call_id,
2918 &state->cli->abstract_syntax,
2919 &state->cli->transfer_syntax,
2920 state->cli->auth->auth_level,
2921 &client_reply,
2922 &state->rpc_out);
2923 data_blob_free(&client_reply);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 return status;
2929 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2930 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2931 if (subreq == NULL) {
2932 return NT_STATUS_NO_MEMORY;
2934 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2935 return NT_STATUS_OK;
2938 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2940 struct tevent_req *req = tevent_req_callback_data(
2941 subreq, struct tevent_req);
2942 struct rpc_pipe_bind_state *state = tevent_req_data(
2943 req, struct rpc_pipe_bind_state);
2944 DATA_BLOB server_spnego_response = data_blob_null;
2945 DATA_BLOB tmp_blob = data_blob_null;
2946 prs_struct reply_pdu;
2947 struct rpc_hdr_info hdr;
2948 struct rpc_hdr_auth_info hdr_auth;
2949 NTSTATUS status;
2951 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2952 TALLOC_FREE(subreq);
2953 if (!NT_STATUS_IS_OK(status)) {
2954 tevent_req_nterror(req, status);
2955 return;
2958 /* Get the auth blob from the reply. */
2959 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) {
2960 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
2961 "unmarshall RPC_HDR.\n"));
2962 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2963 return;
2966 if (!prs_set_offset(
2967 &reply_pdu,
2968 hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
2969 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2970 return;
2973 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
2974 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2975 return;
2978 server_spnego_response = data_blob(NULL, hdr.auth_len);
2979 prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
2980 hdr.auth_len);
2982 /* Check we got a valid auth response. */
2983 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
2984 OID_NTLMSSP, &tmp_blob)) {
2985 data_blob_free(&server_spnego_response);
2986 data_blob_free(&tmp_blob);
2987 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2988 return;
2991 data_blob_free(&server_spnego_response);
2992 data_blob_free(&tmp_blob);
2994 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2995 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2996 tevent_req_done(req);
2999 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3001 return tevent_req_simple_recv_ntstatus(req);
3004 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3005 struct cli_pipe_auth_data *auth)
3007 TALLOC_CTX *frame = talloc_stackframe();
3008 struct event_context *ev;
3009 struct tevent_req *req;
3010 NTSTATUS status = NT_STATUS_OK;
3012 ev = event_context_init(frame);
3013 if (ev == NULL) {
3014 status = NT_STATUS_NO_MEMORY;
3015 goto fail;
3018 req = rpc_pipe_bind_send(frame, ev, cli, auth);
3019 if (req == NULL) {
3020 status = NT_STATUS_NO_MEMORY;
3021 goto fail;
3024 if (!tevent_req_poll(req, ev)) {
3025 status = map_nt_error_from_unix(errno);
3026 goto fail;
3029 status = rpc_pipe_bind_recv(req);
3030 fail:
3031 TALLOC_FREE(frame);
3032 return status;
3035 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3036 unsigned int timeout)
3038 struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
3040 if (cli == NULL) {
3041 return 0;
3043 return cli_set_timeout(cli, timeout);
3046 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3048 struct cli_state *cli;
3050 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3051 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3052 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3053 return true;
3056 cli = rpc_pipe_np_smb_conn(rpc_cli);
3057 if (cli == NULL) {
3058 return false;
3060 E_md4hash(cli->password ? cli->password : "", nt_hash);
3061 return true;
3064 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3065 struct cli_pipe_auth_data **presult)
3067 struct cli_pipe_auth_data *result;
3069 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3070 if (result == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3074 result->auth_type = PIPE_AUTH_TYPE_NONE;
3075 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3077 result->user_name = talloc_strdup(result, "");
3078 result->domain = talloc_strdup(result, "");
3079 if ((result->user_name == NULL) || (result->domain == NULL)) {
3080 TALLOC_FREE(result);
3081 return NT_STATUS_NO_MEMORY;
3084 *presult = result;
3085 return NT_STATUS_OK;
3088 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3090 ntlmssp_end(&auth->a_u.ntlmssp_state);
3091 return 0;
3094 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3095 enum pipe_auth_type auth_type,
3096 enum dcerpc_AuthLevel auth_level,
3097 const char *domain,
3098 const char *username,
3099 const char *password,
3100 struct cli_pipe_auth_data **presult)
3102 struct cli_pipe_auth_data *result;
3103 NTSTATUS status;
3105 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3106 if (result == NULL) {
3107 return NT_STATUS_NO_MEMORY;
3110 result->auth_type = auth_type;
3111 result->auth_level = auth_level;
3113 result->user_name = talloc_strdup(result, username);
3114 result->domain = talloc_strdup(result, domain);
3115 if ((result->user_name == NULL) || (result->domain == NULL)) {
3116 status = NT_STATUS_NO_MEMORY;
3117 goto fail;
3120 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
3121 if (!NT_STATUS_IS_OK(status)) {
3122 goto fail;
3125 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3127 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3128 if (!NT_STATUS_IS_OK(status)) {
3129 goto fail;
3132 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3133 if (!NT_STATUS_IS_OK(status)) {
3134 goto fail;
3137 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 goto fail;
3143 * Turn off sign+seal to allow selected auth level to turn it back on.
3145 result->a_u.ntlmssp_state->neg_flags &=
3146 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3148 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3149 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3150 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3151 result->a_u.ntlmssp_state->neg_flags
3152 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3155 *presult = result;
3156 return NT_STATUS_OK;
3158 fail:
3159 TALLOC_FREE(result);
3160 return status;
3163 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3164 enum dcerpc_AuthLevel auth_level,
3165 struct netlogon_creds_CredentialState *creds,
3166 struct cli_pipe_auth_data **presult)
3168 struct cli_pipe_auth_data *result;
3170 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3171 if (result == NULL) {
3172 return NT_STATUS_NO_MEMORY;
3175 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3176 result->auth_level = auth_level;
3178 result->user_name = talloc_strdup(result, "");
3179 result->domain = talloc_strdup(result, domain);
3180 if ((result->user_name == NULL) || (result->domain == NULL)) {
3181 goto fail;
3184 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3185 if (result->a_u.schannel_auth == NULL) {
3186 goto fail;
3189 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3190 result->a_u.schannel_auth->seq_num = 0;
3191 result->a_u.schannel_auth->initiator = true;
3192 result->a_u.schannel_auth->creds = creds;
3194 *presult = result;
3195 return NT_STATUS_OK;
3197 fail:
3198 TALLOC_FREE(result);
3199 return NT_STATUS_NO_MEMORY;
3202 #ifdef HAVE_KRB5
3203 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3205 data_blob_free(&auth->session_key);
3206 return 0;
3208 #endif
3210 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3211 enum dcerpc_AuthLevel auth_level,
3212 const char *service_princ,
3213 const char *username,
3214 const char *password,
3215 struct cli_pipe_auth_data **presult)
3217 #ifdef HAVE_KRB5
3218 struct cli_pipe_auth_data *result;
3220 if ((username != NULL) && (password != NULL)) {
3221 int ret = kerberos_kinit_password(username, password, 0, NULL);
3222 if (ret != 0) {
3223 return NT_STATUS_ACCESS_DENIED;
3227 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3228 if (result == NULL) {
3229 return NT_STATUS_NO_MEMORY;
3232 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3233 result->auth_level = auth_level;
3236 * Username / domain need fixing!
3238 result->user_name = talloc_strdup(result, "");
3239 result->domain = talloc_strdup(result, "");
3240 if ((result->user_name == NULL) || (result->domain == NULL)) {
3241 goto fail;
3244 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3245 result, struct kerberos_auth_struct);
3246 if (result->a_u.kerberos_auth == NULL) {
3247 goto fail;
3249 talloc_set_destructor(result->a_u.kerberos_auth,
3250 cli_auth_kerberos_data_destructor);
3252 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3253 result, service_princ);
3254 if (result->a_u.kerberos_auth->service_principal == NULL) {
3255 goto fail;
3258 *presult = result;
3259 return NT_STATUS_OK;
3261 fail:
3262 TALLOC_FREE(result);
3263 return NT_STATUS_NO_MEMORY;
3264 #else
3265 return NT_STATUS_NOT_SUPPORTED;
3266 #endif
3270 * Create an rpc pipe client struct, connecting to a tcp port.
3272 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3273 uint16_t port,
3274 const struct ndr_syntax_id *abstract_syntax,
3275 struct rpc_pipe_client **presult)
3277 struct rpc_pipe_client *result;
3278 struct sockaddr_storage addr;
3279 NTSTATUS status;
3280 int fd;
3282 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3283 if (result == NULL) {
3284 return NT_STATUS_NO_MEMORY;
3287 result->abstract_syntax = *abstract_syntax;
3288 result->transfer_syntax = ndr_transfer_syntax;
3289 result->dispatch = cli_do_rpc_ndr;
3290 result->dispatch_send = cli_do_rpc_ndr_send;
3291 result->dispatch_recv = cli_do_rpc_ndr_recv;
3293 result->desthost = talloc_strdup(result, host);
3294 result->srv_name_slash = talloc_asprintf_strupper_m(
3295 result, "\\\\%s", result->desthost);
3296 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3297 status = NT_STATUS_NO_MEMORY;
3298 goto fail;
3301 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3302 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3304 if (!resolve_name(host, &addr, 0, false)) {
3305 status = NT_STATUS_NOT_FOUND;
3306 goto fail;
3309 status = open_socket_out(&addr, port, 60, &fd);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 goto fail;
3313 set_socket_options(fd, lp_socket_options());
3315 status = rpc_transport_sock_init(result, fd, &result->transport);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 close(fd);
3318 goto fail;
3321 result->transport->transport = NCACN_IP_TCP;
3323 *presult = result;
3324 return NT_STATUS_OK;
3326 fail:
3327 TALLOC_FREE(result);
3328 return status;
3332 * Determine the tcp port on which a dcerpc interface is listening
3333 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3334 * target host.
3336 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3337 const struct ndr_syntax_id *abstract_syntax,
3338 uint16_t *pport)
3340 NTSTATUS status;
3341 struct rpc_pipe_client *epm_pipe = NULL;
3342 struct cli_pipe_auth_data *auth = NULL;
3343 struct dcerpc_binding *map_binding = NULL;
3344 struct dcerpc_binding *res_binding = NULL;
3345 struct epm_twr_t *map_tower = NULL;
3346 struct epm_twr_t *res_towers = NULL;
3347 struct policy_handle *entry_handle = NULL;
3348 uint32_t num_towers = 0;
3349 uint32_t max_towers = 1;
3350 struct epm_twr_p_t towers;
3351 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3353 if (pport == NULL) {
3354 status = NT_STATUS_INVALID_PARAMETER;
3355 goto done;
3358 /* open the connection to the endpoint mapper */
3359 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3360 &ndr_table_epmapper.syntax_id,
3361 &epm_pipe);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 goto done;
3367 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3368 if (!NT_STATUS_IS_OK(status)) {
3369 goto done;
3372 status = rpc_pipe_bind(epm_pipe, auth);
3373 if (!NT_STATUS_IS_OK(status)) {
3374 goto done;
3377 /* create tower for asking the epmapper */
3379 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3380 if (map_binding == NULL) {
3381 status = NT_STATUS_NO_MEMORY;
3382 goto done;
3385 map_binding->transport = NCACN_IP_TCP;
3386 map_binding->object = *abstract_syntax;
3387 map_binding->host = host; /* needed? */
3388 map_binding->endpoint = "0"; /* correct? needed? */
3390 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3391 if (map_tower == NULL) {
3392 status = NT_STATUS_NO_MEMORY;
3393 goto done;
3396 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3397 &(map_tower->tower));
3398 if (!NT_STATUS_IS_OK(status)) {
3399 goto done;
3402 /* allocate further parameters for the epm_Map call */
3404 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3405 if (res_towers == NULL) {
3406 status = NT_STATUS_NO_MEMORY;
3407 goto done;
3409 towers.twr = res_towers;
3411 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3412 if (entry_handle == NULL) {
3413 status = NT_STATUS_NO_MEMORY;
3414 goto done;
3417 /* ask the endpoint mapper for the port */
3419 status = rpccli_epm_Map(epm_pipe,
3420 tmp_ctx,
3421 CONST_DISCARD(struct GUID *,
3422 &(abstract_syntax->uuid)),
3423 map_tower,
3424 entry_handle,
3425 max_towers,
3426 &num_towers,
3427 &towers);
3429 if (!NT_STATUS_IS_OK(status)) {
3430 goto done;
3433 if (num_towers != 1) {
3434 status = NT_STATUS_UNSUCCESSFUL;
3435 goto done;
3438 /* extract the port from the answer */
3440 status = dcerpc_binding_from_tower(tmp_ctx,
3441 &(towers.twr->tower),
3442 &res_binding);
3443 if (!NT_STATUS_IS_OK(status)) {
3444 goto done;
3447 /* are further checks here necessary? */
3448 if (res_binding->transport != NCACN_IP_TCP) {
3449 status = NT_STATUS_UNSUCCESSFUL;
3450 goto done;
3453 *pport = (uint16_t)atoi(res_binding->endpoint);
3455 done:
3456 TALLOC_FREE(tmp_ctx);
3457 return status;
3461 * Create a rpc pipe client struct, connecting to a host via tcp.
3462 * The port is determined by asking the endpoint mapper on the given
3463 * host.
3465 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3466 const struct ndr_syntax_id *abstract_syntax,
3467 struct rpc_pipe_client **presult)
3469 NTSTATUS status;
3470 uint16_t port = 0;
3472 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3473 if (!NT_STATUS_IS_OK(status)) {
3474 return status;
3477 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3478 abstract_syntax, presult);
3481 /********************************************************************
3482 Create a rpc pipe client struct, connecting to a unix domain socket
3483 ********************************************************************/
3484 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3485 const struct ndr_syntax_id *abstract_syntax,
3486 struct rpc_pipe_client **presult)
3488 struct rpc_pipe_client *result;
3489 struct sockaddr_un addr;
3490 NTSTATUS status;
3491 int fd;
3493 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3494 if (result == NULL) {
3495 return NT_STATUS_NO_MEMORY;
3498 result->abstract_syntax = *abstract_syntax;
3499 result->transfer_syntax = ndr_transfer_syntax;
3500 result->dispatch = cli_do_rpc_ndr;
3501 result->dispatch_send = cli_do_rpc_ndr_send;
3502 result->dispatch_recv = cli_do_rpc_ndr_recv;
3504 result->desthost = get_myname(result);
3505 result->srv_name_slash = talloc_asprintf_strupper_m(
3506 result, "\\\\%s", result->desthost);
3507 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3508 status = NT_STATUS_NO_MEMORY;
3509 goto fail;
3512 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3513 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3515 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3516 if (fd == -1) {
3517 status = map_nt_error_from_unix(errno);
3518 goto fail;
3521 ZERO_STRUCT(addr);
3522 addr.sun_family = AF_UNIX;
3523 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3525 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3526 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3527 strerror(errno)));
3528 close(fd);
3529 return map_nt_error_from_unix(errno);
3532 status = rpc_transport_sock_init(result, fd, &result->transport);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 close(fd);
3535 goto fail;
3538 result->transport->transport = NCALRPC;
3540 *presult = result;
3541 return NT_STATUS_OK;
3543 fail:
3544 TALLOC_FREE(result);
3545 return status;
3548 static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p)
3550 struct cli_state *cli;
3552 cli = rpc_pipe_np_smb_conn(p);
3553 if (cli != NULL) {
3554 DLIST_REMOVE(cli->pipe_list, p);
3556 return 0;
3559 /****************************************************************************
3560 Open a named pipe over SMB to a remote server.
3562 * CAVEAT CALLER OF THIS FUNCTION:
3563 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3564 * so be sure that this function is called AFTER any structure (vs pointer)
3565 * assignment of the cli. In particular, libsmbclient does structure
3566 * assignments of cli, which invalidates the data in the returned
3567 * rpc_pipe_client if this function is called before the structure assignment
3568 * of cli.
3570 ****************************************************************************/
3572 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3573 const struct ndr_syntax_id *abstract_syntax,
3574 struct rpc_pipe_client **presult)
3576 struct rpc_pipe_client *result;
3577 NTSTATUS status;
3579 /* sanity check to protect against crashes */
3581 if ( !cli ) {
3582 return NT_STATUS_INVALID_HANDLE;
3585 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3586 if (result == NULL) {
3587 return NT_STATUS_NO_MEMORY;
3590 result->abstract_syntax = *abstract_syntax;
3591 result->transfer_syntax = ndr_transfer_syntax;
3592 result->dispatch = cli_do_rpc_ndr;
3593 result->dispatch_send = cli_do_rpc_ndr_send;
3594 result->dispatch_recv = cli_do_rpc_ndr_recv;
3595 result->desthost = talloc_strdup(result, cli->desthost);
3596 result->srv_name_slash = talloc_asprintf_strupper_m(
3597 result, "\\\\%s", result->desthost);
3599 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3600 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3602 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3603 TALLOC_FREE(result);
3604 return NT_STATUS_NO_MEMORY;
3607 status = rpc_transport_np_init(result, cli, abstract_syntax,
3608 &result->transport);
3609 if (!NT_STATUS_IS_OK(status)) {
3610 TALLOC_FREE(result);
3611 return status;
3614 result->transport->transport = NCACN_NP;
3616 DLIST_ADD(cli->pipe_list, result);
3617 talloc_set_destructor(result, rpc_pipe_client_np_destructor);
3619 *presult = result;
3620 return NT_STATUS_OK;
3623 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3624 struct rpc_cli_smbd_conn *conn,
3625 const struct ndr_syntax_id *syntax,
3626 struct rpc_pipe_client **presult)
3628 struct rpc_pipe_client *result;
3629 struct cli_pipe_auth_data *auth;
3630 NTSTATUS status;
3632 result = talloc(mem_ctx, struct rpc_pipe_client);
3633 if (result == NULL) {
3634 return NT_STATUS_NO_MEMORY;
3636 result->abstract_syntax = *syntax;
3637 result->transfer_syntax = ndr_transfer_syntax;
3638 result->dispatch = cli_do_rpc_ndr;
3639 result->dispatch_send = cli_do_rpc_ndr_send;
3640 result->dispatch_recv = cli_do_rpc_ndr_recv;
3641 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3642 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3644 result->desthost = talloc_strdup(result, global_myname());
3645 result->srv_name_slash = talloc_asprintf_strupper_m(
3646 result, "\\\\%s", global_myname());
3647 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3648 TALLOC_FREE(result);
3649 return NT_STATUS_NO_MEMORY;
3652 status = rpc_transport_smbd_init(result, conn, syntax,
3653 &result->transport);
3654 if (!NT_STATUS_IS_OK(status)) {
3655 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3656 nt_errstr(status)));
3657 TALLOC_FREE(result);
3658 return status;
3661 status = rpccli_anon_bind_data(result, &auth);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3664 nt_errstr(status)));
3665 TALLOC_FREE(result);
3666 return status;
3669 status = rpc_pipe_bind(result, auth);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3672 TALLOC_FREE(result);
3673 return status;
3676 result->transport->transport = NCACN_INTERNAL;
3678 *presult = result;
3679 return NT_STATUS_OK;
3682 /****************************************************************************
3683 Open a pipe to a remote server.
3684 ****************************************************************************/
3686 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3687 enum dcerpc_transport_t transport,
3688 const struct ndr_syntax_id *interface,
3689 struct rpc_pipe_client **presult)
3691 switch (transport) {
3692 case NCACN_IP_TCP:
3693 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3694 presult);
3695 case NCACN_NP:
3696 return rpc_pipe_open_np(cli, interface, presult);
3697 default:
3698 return NT_STATUS_NOT_IMPLEMENTED;
3702 /****************************************************************************
3703 Open a named pipe to an SMB server and bind anonymously.
3704 ****************************************************************************/
3706 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3707 enum dcerpc_transport_t transport,
3708 const struct ndr_syntax_id *interface,
3709 struct rpc_pipe_client **presult)
3711 struct rpc_pipe_client *result;
3712 struct cli_pipe_auth_data *auth;
3713 NTSTATUS status;
3715 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 return status;
3720 status = rpccli_anon_bind_data(result, &auth);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3723 nt_errstr(status)));
3724 TALLOC_FREE(result);
3725 return status;
3729 * This is a bit of an abstraction violation due to the fact that an
3730 * anonymous bind on an authenticated SMB inherits the user/domain
3731 * from the enclosing SMB creds
3734 TALLOC_FREE(auth->user_name);
3735 TALLOC_FREE(auth->domain);
3737 auth->user_name = talloc_strdup(auth, cli->user_name);
3738 auth->domain = talloc_strdup(auth, cli->domain);
3739 auth->user_session_key = data_blob_talloc(auth,
3740 cli->user_session_key.data,
3741 cli->user_session_key.length);
3743 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3744 TALLOC_FREE(result);
3745 return NT_STATUS_NO_MEMORY;
3748 status = rpc_pipe_bind(result, auth);
3749 if (!NT_STATUS_IS_OK(status)) {
3750 int lvl = 0;
3751 if (ndr_syntax_id_equal(interface,
3752 &ndr_table_dssetup.syntax_id)) {
3753 /* non AD domains just don't have this pipe, avoid
3754 * level 0 statement in that case - gd */
3755 lvl = 3;
3757 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3758 "%s failed with error %s\n",
3759 get_pipe_name_from_syntax(talloc_tos(), interface),
3760 nt_errstr(status) ));
3761 TALLOC_FREE(result);
3762 return status;
3765 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3766 "%s and bound anonymously.\n",
3767 get_pipe_name_from_syntax(talloc_tos(), interface),
3768 cli->desthost));
3770 *presult = result;
3771 return NT_STATUS_OK;
3774 /****************************************************************************
3775 ****************************************************************************/
3777 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3778 const struct ndr_syntax_id *interface,
3779 struct rpc_pipe_client **presult)
3781 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3782 interface, presult);
3785 /****************************************************************************
3786 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3787 ****************************************************************************/
3789 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3790 const struct ndr_syntax_id *interface,
3791 enum dcerpc_transport_t transport,
3792 enum pipe_auth_type auth_type,
3793 enum dcerpc_AuthLevel auth_level,
3794 const char *domain,
3795 const char *username,
3796 const char *password,
3797 struct rpc_pipe_client **presult)
3799 struct rpc_pipe_client *result;
3800 struct cli_pipe_auth_data *auth;
3801 NTSTATUS status;
3803 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 return status;
3808 status = rpccli_ntlmssp_bind_data(
3809 result, auth_type, auth_level, domain, username,
3810 password, &auth);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3813 nt_errstr(status)));
3814 goto err;
3817 status = rpc_pipe_bind(result, auth);
3818 if (!NT_STATUS_IS_OK(status)) {
3819 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3820 nt_errstr(status) ));
3821 goto err;
3824 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3825 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3826 get_pipe_name_from_syntax(talloc_tos(), interface),
3827 cli->desthost, domain, username ));
3829 *presult = result;
3830 return NT_STATUS_OK;
3832 err:
3834 TALLOC_FREE(result);
3835 return status;
3838 /****************************************************************************
3839 External interface.
3840 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3841 ****************************************************************************/
3843 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3844 const struct ndr_syntax_id *interface,
3845 enum dcerpc_transport_t transport,
3846 enum dcerpc_AuthLevel auth_level,
3847 const char *domain,
3848 const char *username,
3849 const char *password,
3850 struct rpc_pipe_client **presult)
3852 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3853 interface,
3854 transport,
3855 PIPE_AUTH_TYPE_NTLMSSP,
3856 auth_level,
3857 domain,
3858 username,
3859 password,
3860 presult);
3863 /****************************************************************************
3864 External interface.
3865 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3866 ****************************************************************************/
3868 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3869 const struct ndr_syntax_id *interface,
3870 enum dcerpc_transport_t transport,
3871 enum dcerpc_AuthLevel auth_level,
3872 const char *domain,
3873 const char *username,
3874 const char *password,
3875 struct rpc_pipe_client **presult)
3877 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3878 interface,
3879 transport,
3880 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3881 auth_level,
3882 domain,
3883 username,
3884 password,
3885 presult);
3888 /****************************************************************************
3889 Get a the schannel session key out of an already opened netlogon pipe.
3890 ****************************************************************************/
3891 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3892 struct cli_state *cli,
3893 const char *domain,
3894 uint32 *pneg_flags)
3896 enum netr_SchannelType sec_chan_type = 0;
3897 unsigned char machine_pwd[16];
3898 const char *machine_account;
3899 NTSTATUS status;
3901 /* Get the machine account credentials from secrets.tdb. */
3902 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3903 &sec_chan_type))
3905 DEBUG(0, ("get_schannel_session_key: could not fetch "
3906 "trust account password for domain '%s'\n",
3907 domain));
3908 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3911 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3912 cli->desthost, /* server name */
3913 domain, /* domain */
3914 global_myname(), /* client name */
3915 machine_account, /* machine account name */
3916 machine_pwd,
3917 sec_chan_type,
3918 pneg_flags);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 DEBUG(3, ("get_schannel_session_key_common: "
3922 "rpccli_netlogon_setup_creds failed with result %s "
3923 "to server %s, domain %s, machine account %s.\n",
3924 nt_errstr(status), cli->desthost, domain,
3925 machine_account ));
3926 return status;
3929 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3930 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3931 cli->desthost));
3932 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3935 return NT_STATUS_OK;;
3938 /****************************************************************************
3939 Open a netlogon pipe and get the schannel session key.
3940 Now exposed to external callers.
3941 ****************************************************************************/
3944 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3945 const char *domain,
3946 uint32 *pneg_flags,
3947 struct rpc_pipe_client **presult)
3949 struct rpc_pipe_client *netlogon_pipe = NULL;
3950 NTSTATUS status;
3952 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3953 &netlogon_pipe);
3954 if (!NT_STATUS_IS_OK(status)) {
3955 return status;
3958 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3959 pneg_flags);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 TALLOC_FREE(netlogon_pipe);
3962 return status;
3965 *presult = netlogon_pipe;
3966 return NT_STATUS_OK;
3969 /****************************************************************************
3970 External interface.
3971 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3972 using session_key. sign and seal.
3974 The *pdc will be stolen onto this new pipe
3975 ****************************************************************************/
3977 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3978 const struct ndr_syntax_id *interface,
3979 enum dcerpc_transport_t transport,
3980 enum dcerpc_AuthLevel auth_level,
3981 const char *domain,
3982 struct netlogon_creds_CredentialState **pdc,
3983 struct rpc_pipe_client **presult)
3985 struct rpc_pipe_client *result;
3986 struct cli_pipe_auth_data *auth;
3987 NTSTATUS status;
3989 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 return status;
3994 status = rpccli_schannel_bind_data(result, domain, auth_level,
3995 *pdc, &auth);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3998 nt_errstr(status)));
3999 TALLOC_FREE(result);
4000 return status;
4003 status = rpc_pipe_bind(result, auth);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4006 "cli_rpc_pipe_bind failed with error %s\n",
4007 nt_errstr(status) ));
4008 TALLOC_FREE(result);
4009 return status;
4013 * The credentials on a new netlogon pipe are the ones we are passed
4014 * in - reference them in
4016 result->dc = talloc_move(result, pdc);
4018 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4019 "for domain %s and bound using schannel.\n",
4020 get_pipe_name_from_syntax(talloc_tos(), interface),
4021 cli->desthost, domain ));
4023 *presult = result;
4024 return NT_STATUS_OK;
4027 /****************************************************************************
4028 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4029 Fetch the session key ourselves using a temporary netlogon pipe. This
4030 version uses an ntlmssp auth bound netlogon pipe to get the key.
4031 ****************************************************************************/
4033 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4034 const char *domain,
4035 const char *username,
4036 const char *password,
4037 uint32 *pneg_flags,
4038 struct rpc_pipe_client **presult)
4040 struct rpc_pipe_client *netlogon_pipe = NULL;
4041 NTSTATUS status;
4043 status = cli_rpc_pipe_open_spnego_ntlmssp(
4044 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4045 DCERPC_AUTH_LEVEL_PRIVACY,
4046 domain, username, password, &netlogon_pipe);
4047 if (!NT_STATUS_IS_OK(status)) {
4048 return status;
4051 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4052 pneg_flags);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 TALLOC_FREE(netlogon_pipe);
4055 return status;
4058 *presult = netlogon_pipe;
4059 return NT_STATUS_OK;
4062 /****************************************************************************
4063 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4064 Fetch the session key ourselves using a temporary netlogon pipe. This version
4065 uses an ntlmssp bind to get the session key.
4066 ****************************************************************************/
4068 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4069 const struct ndr_syntax_id *interface,
4070 enum dcerpc_transport_t transport,
4071 enum dcerpc_AuthLevel auth_level,
4072 const char *domain,
4073 const char *username,
4074 const char *password,
4075 struct rpc_pipe_client **presult)
4077 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4078 struct rpc_pipe_client *netlogon_pipe = NULL;
4079 struct rpc_pipe_client *result = NULL;
4080 NTSTATUS status;
4082 status = get_schannel_session_key_auth_ntlmssp(
4083 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4084 if (!NT_STATUS_IS_OK(status)) {
4085 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4086 "key from server %s for domain %s.\n",
4087 cli->desthost, domain ));
4088 return status;
4091 status = cli_rpc_pipe_open_schannel_with_key(
4092 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4093 &result);
4095 /* Now we've bound using the session key we can close the netlog pipe. */
4096 TALLOC_FREE(netlogon_pipe);
4098 if (NT_STATUS_IS_OK(status)) {
4099 *presult = result;
4101 return status;
4104 /****************************************************************************
4105 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4106 Fetch the session key ourselves using a temporary netlogon pipe.
4107 ****************************************************************************/
4109 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4110 const struct ndr_syntax_id *interface,
4111 enum dcerpc_transport_t transport,
4112 enum dcerpc_AuthLevel auth_level,
4113 const char *domain,
4114 struct rpc_pipe_client **presult)
4116 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4117 struct rpc_pipe_client *netlogon_pipe = NULL;
4118 struct rpc_pipe_client *result = NULL;
4119 NTSTATUS status;
4121 status = get_schannel_session_key(cli, domain, &neg_flags,
4122 &netlogon_pipe);
4123 if (!NT_STATUS_IS_OK(status)) {
4124 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4125 "key from server %s for domain %s.\n",
4126 cli->desthost, domain ));
4127 return status;
4130 status = cli_rpc_pipe_open_schannel_with_key(
4131 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4132 &result);
4134 /* Now we've bound using the session key we can close the netlog pipe. */
4135 TALLOC_FREE(netlogon_pipe);
4137 if (NT_STATUS_IS_OK(status)) {
4138 *presult = result;
4141 return status;
4144 /****************************************************************************
4145 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4146 The idea is this can be called with service_princ, username and password all
4147 NULL so long as the caller has a TGT.
4148 ****************************************************************************/
4150 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4151 const struct ndr_syntax_id *interface,
4152 enum dcerpc_AuthLevel auth_level,
4153 const char *service_princ,
4154 const char *username,
4155 const char *password,
4156 struct rpc_pipe_client **presult)
4158 #ifdef HAVE_KRB5
4159 struct rpc_pipe_client *result;
4160 struct cli_pipe_auth_data *auth;
4161 NTSTATUS status;
4163 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 return status;
4168 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4169 username, password, &auth);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4172 nt_errstr(status)));
4173 TALLOC_FREE(result);
4174 return status;
4177 status = rpc_pipe_bind(result, auth);
4178 if (!NT_STATUS_IS_OK(status)) {
4179 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4180 "with error %s\n", nt_errstr(status)));
4181 TALLOC_FREE(result);
4182 return status;
4185 *presult = result;
4186 return NT_STATUS_OK;
4187 #else
4188 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4189 return NT_STATUS_NOT_IMPLEMENTED;
4190 #endif
4193 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4194 struct rpc_pipe_client *cli,
4195 DATA_BLOB *session_key)
4197 if (!session_key || !cli) {
4198 return NT_STATUS_INVALID_PARAMETER;
4201 if (!cli->auth) {
4202 return NT_STATUS_INVALID_PARAMETER;
4205 switch (cli->auth->auth_type) {
4206 case PIPE_AUTH_TYPE_SCHANNEL:
4207 *session_key = data_blob_talloc(mem_ctx,
4208 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4209 break;
4210 case PIPE_AUTH_TYPE_NTLMSSP:
4211 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4212 *session_key = data_blob_talloc(mem_ctx,
4213 cli->auth->a_u.ntlmssp_state->session_key.data,
4214 cli->auth->a_u.ntlmssp_state->session_key.length);
4215 break;
4216 case PIPE_AUTH_TYPE_KRB5:
4217 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4218 *session_key = data_blob_talloc(mem_ctx,
4219 cli->auth->a_u.kerberos_auth->session_key.data,
4220 cli->auth->a_u.kerberos_auth->session_key.length);
4221 break;
4222 case PIPE_AUTH_TYPE_NONE:
4223 *session_key = data_blob_talloc(mem_ctx,
4224 cli->auth->user_session_key.data,
4225 cli->auth->user_session_key.length);
4226 break;
4227 default:
4228 return NT_STATUS_NO_USER_SESSION_KEY;
4231 return NT_STATUS_OK;