s3-spoolss: fix _spoolss_GetPrinterDataEx after IDL change.
[Samba/nascimento.git] / source3 / rpc_client / cli_pipe.c
blob2f7db99f205deab49396b6351cd092a5b79afd22
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 "librpc/gen_ndr/cli_epmapper.h"
22 #include "../librpc/gen_ndr/ndr_schannel.h"
23 #include "../libcli/auth/schannel.h"
24 #include "../libcli/auth/spnego.h"
25 #include "smb_krb5.h"
26 #include "ntlmssp.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 struct 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_PDU_FRAG_LEN ||
654 prhdr->frag_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
655 RPC_HDR_AUTH_LEN + auth_len) {
656 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
657 (unsigned int)auth_len ));
658 return NT_STATUS_BUFFER_TOO_SMALL;
662 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
663 * after the RPC header.
664 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
665 * functions as NTLMv2 checks the rpc headers also.
668 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
669 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
671 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
672 full_packet_data_len = prhdr->frag_len - auth_len;
674 /* Pull the auth header and the following data into a blob. */
675 /* NB. The offset of the auth_header is relative to the *end*
676 * of the packet, not the start. */
677 if(!prs_set_offset(current_pdu, prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
678 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
679 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
680 return NT_STATUS_BUFFER_TOO_SMALL;
683 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
684 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
685 return NT_STATUS_BUFFER_TOO_SMALL;
688 /* Ensure auth_pad_len fits into the packet. */
689 if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
690 RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
691 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
692 "too large (%u), auth_len (%u), frag_len = (%u).\n",
693 (unsigned int)auth_info.auth_pad_len,
694 (unsigned int)auth_len,
695 (unsigned int)prhdr->frag_len ));
696 return NT_STATUS_BUFFER_TOO_SMALL;
700 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
701 auth_blob.length = auth_len;
703 switch (cli->auth->auth_level) {
704 case DCERPC_AUTH_LEVEL_PRIVACY:
705 /* Data is encrypted. */
706 status = ntlmssp_unseal_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: failed to unseal "
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 case DCERPC_AUTH_LEVEL_INTEGRITY:
720 /* Data is signed. */
721 status = ntlmssp_check_packet(ntlmssp_state,
722 data, data_len,
723 full_packet_data,
724 full_packet_data_len,
725 &auth_blob);
726 if (!NT_STATUS_IS_OK(status)) {
727 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
728 "packet from %s. Error was %s.\n",
729 rpccli_pipe_txt(talloc_tos(), cli),
730 nt_errstr(status) ));
731 return status;
733 break;
734 default:
735 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
736 "auth level %d\n", cli->auth->auth_level));
737 return NT_STATUS_INVALID_INFO_CLASS;
741 * Return the current pointer to the data offset.
744 if(!prs_set_offset(current_pdu, save_offset)) {
745 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
746 (unsigned int)save_offset ));
747 return NT_STATUS_BUFFER_TOO_SMALL;
751 * Remember the padding length. We must remove it from the real data
752 * stream once the sign/seal is done.
755 *p_ss_padding_len = auth_info.auth_pad_len;
757 return NT_STATUS_OK;
760 /****************************************************************************
761 schannel specific sign/seal.
762 ****************************************************************************/
764 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
765 prs_struct *current_pdu,
766 uint8 *p_ss_padding_len)
768 RPC_HDR_AUTH auth_info;
769 uint32 auth_len = prhdr->auth_len;
770 uint32 save_offset = prs_offset(current_pdu);
771 struct schannel_state *schannel_auth =
772 cli->auth->a_u.schannel_auth;
773 uint8_t *data;
774 uint32 data_len;
775 DATA_BLOB blob;
776 NTSTATUS status;
778 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
779 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
780 return NT_STATUS_OK;
783 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
784 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
785 return NT_STATUS_INVALID_PARAMETER;
788 if (!schannel_auth) {
789 return NT_STATUS_INVALID_PARAMETER;
792 /* Ensure there's enough data for an authenticated response. */
793 if ((auth_len > RPC_MAX_PDU_FRAG_LEN) ||
794 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
795 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
796 (unsigned int)auth_len ));
797 return NT_STATUS_INVALID_PARAMETER;
800 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
802 /* Pull the auth header and the following data into a blob. */
803 /* NB. The offset of the auth_header is relative to the *end*
804 * of the packet, not the start. */
805 if(!prs_set_offset(current_pdu,
806 prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
807 DEBUG(0,("cli_pipe_verify_schannel: cannot move "
808 "offset to %u.\n",
809 (unsigned int)(prhdr->frag_len -
810 RPC_HDR_AUTH_LEN - auth_len) ));
811 return NT_STATUS_BUFFER_TOO_SMALL;
814 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
815 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
816 return NT_STATUS_BUFFER_TOO_SMALL;
819 /* Ensure auth_pad_len fits into the packet. */
820 if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
821 RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
822 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
823 "too large (%u), auth_len (%u), frag_len = (%u).\n",
824 (unsigned int)auth_info.auth_pad_len,
825 (unsigned int)auth_len,
826 (unsigned int)prhdr->frag_len ));
827 return NT_STATUS_BUFFER_TOO_SMALL;
830 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
831 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
832 auth_info.auth_type));
833 return NT_STATUS_BUFFER_TOO_SMALL;
836 blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), auth_len);
838 if (DEBUGLEVEL >= 10) {
839 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
842 data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
844 switch (cli->auth->auth_level) {
845 case DCERPC_AUTH_LEVEL_PRIVACY:
846 status = netsec_incoming_packet(schannel_auth,
847 talloc_tos(),
848 true,
849 data,
850 data_len,
851 &blob);
852 break;
853 case DCERPC_AUTH_LEVEL_INTEGRITY:
854 status = netsec_incoming_packet(schannel_auth,
855 talloc_tos(),
856 false,
857 data,
858 data_len,
859 &blob);
860 break;
861 default:
862 status = NT_STATUS_INTERNAL_ERROR;
863 break;
866 if (!NT_STATUS_IS_OK(status)) {
867 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
868 "Connection to %s (%s).\n",
869 rpccli_pipe_txt(talloc_tos(), cli),
870 nt_errstr(status)));
871 return NT_STATUS_INVALID_PARAMETER;
875 * Return the current pointer to the data offset.
878 if(!prs_set_offset(current_pdu, save_offset)) {
879 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
880 (unsigned int)save_offset ));
881 return NT_STATUS_BUFFER_TOO_SMALL;
885 * Remember the padding length. We must remove it from the real data
886 * stream once the sign/seal is done.
889 *p_ss_padding_len = auth_info.auth_pad_len;
891 return NT_STATUS_OK;
894 /****************************************************************************
895 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
896 ****************************************************************************/
898 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
899 prs_struct *current_pdu,
900 uint8 *p_ss_padding_len)
902 NTSTATUS ret = NT_STATUS_OK;
904 /* Paranioa checks for auth_len. */
905 if (prhdr->auth_len) {
906 if (prhdr->auth_len > prhdr->frag_len) {
907 return NT_STATUS_INVALID_PARAMETER;
910 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
911 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
912 /* Integer wrap attempt. */
913 return NT_STATUS_INVALID_PARAMETER;
918 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
921 switch(cli->auth->auth_type) {
922 case PIPE_AUTH_TYPE_NONE:
923 if (prhdr->auth_len) {
924 DEBUG(3, ("cli_pipe_validate_rpc_response: "
925 "Connection to %s - got non-zero "
926 "auth len %u.\n",
927 rpccli_pipe_txt(talloc_tos(), cli),
928 (unsigned int)prhdr->auth_len ));
929 return NT_STATUS_INVALID_PARAMETER;
931 break;
933 case PIPE_AUTH_TYPE_NTLMSSP:
934 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
935 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
936 if (!NT_STATUS_IS_OK(ret)) {
937 return ret;
939 break;
941 case PIPE_AUTH_TYPE_SCHANNEL:
942 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
943 if (!NT_STATUS_IS_OK(ret)) {
944 return ret;
946 break;
948 case PIPE_AUTH_TYPE_KRB5:
949 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
950 default:
951 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
952 "to %s - unknown internal auth type %u.\n",
953 rpccli_pipe_txt(talloc_tos(), cli),
954 cli->auth->auth_type ));
955 return NT_STATUS_INVALID_INFO_CLASS;
958 return NT_STATUS_OK;
961 /****************************************************************************
962 Do basic authentication checks on an incoming pdu.
963 ****************************************************************************/
965 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
966 prs_struct *current_pdu,
967 uint8 expected_pkt_type,
968 char **ppdata,
969 uint32 *pdata_len,
970 prs_struct *return_data)
973 NTSTATUS ret = NT_STATUS_OK;
974 uint32 current_pdu_len = prs_data_size(current_pdu);
976 if (current_pdu_len != prhdr->frag_len) {
977 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
978 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
979 return NT_STATUS_INVALID_PARAMETER;
983 * Point the return values at the real data including the RPC
984 * header. Just in case the caller wants it.
986 *ppdata = prs_data_p(current_pdu);
987 *pdata_len = current_pdu_len;
989 /* Ensure we have the correct type. */
990 switch (prhdr->pkt_type) {
991 case DCERPC_PKT_ALTER_RESP:
992 case DCERPC_PKT_BIND_ACK:
994 /* Alter context and bind ack share the same packet definitions. */
995 break;
998 case DCERPC_PKT_RESPONSE:
1000 RPC_HDR_RESP rhdr_resp;
1001 uint8 ss_padding_len = 0;
1003 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1004 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1005 return NT_STATUS_BUFFER_TOO_SMALL;
1008 /* Here's where we deal with incoming sign/seal. */
1009 ret = cli_pipe_validate_rpc_response(cli, prhdr,
1010 current_pdu, &ss_padding_len);
1011 if (!NT_STATUS_IS_OK(ret)) {
1012 return ret;
1015 /* Point the return values at the NDR data. Remember to remove any ss padding. */
1016 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1018 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
1019 return NT_STATUS_BUFFER_TOO_SMALL;
1022 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
1024 /* Remember to remove the auth footer. */
1025 if (prhdr->auth_len) {
1026 /* We've already done integer wrap tests on auth_len in
1027 cli_pipe_validate_rpc_response(). */
1028 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
1029 return NT_STATUS_BUFFER_TOO_SMALL;
1031 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
1034 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
1035 current_pdu_len, *pdata_len, ss_padding_len ));
1038 * If this is the first reply, and the allocation hint is reasonably, try and
1039 * set up the return_data parse_struct to the correct size.
1042 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
1043 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
1044 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
1045 "too large to allocate\n",
1046 (unsigned int)rhdr_resp.alloc_hint ));
1047 return NT_STATUS_NO_MEMORY;
1051 break;
1054 case DCERPC_PKT_BIND_NAK:
1055 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1056 "received from %s!\n",
1057 rpccli_pipe_txt(talloc_tos(), cli)));
1058 /* Use this for now... */
1059 return NT_STATUS_NETWORK_ACCESS_DENIED;
1061 case DCERPC_PKT_FAULT:
1063 RPC_HDR_RESP rhdr_resp;
1064 RPC_HDR_FAULT fault_resp;
1066 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1067 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1068 return NT_STATUS_BUFFER_TOO_SMALL;
1071 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
1072 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
1073 return NT_STATUS_BUFFER_TOO_SMALL;
1076 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1077 "code %s received from %s!\n",
1078 dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
1079 rpccli_pipe_txt(talloc_tos(), cli)));
1080 if (NT_STATUS_IS_OK(fault_resp.status)) {
1081 return NT_STATUS_UNSUCCESSFUL;
1082 } else {
1083 return fault_resp.status;
1087 default:
1088 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
1089 "from %s!\n",
1090 (unsigned int)prhdr->pkt_type,
1091 rpccli_pipe_txt(talloc_tos(), cli)));
1092 return NT_STATUS_INVALID_INFO_CLASS;
1095 if (prhdr->pkt_type != expected_pkt_type) {
1096 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1097 "got an unexpected RPC packet type - %u, not %u\n",
1098 rpccli_pipe_txt(talloc_tos(), cli),
1099 prhdr->pkt_type,
1100 expected_pkt_type));
1101 return NT_STATUS_INVALID_INFO_CLASS;
1104 /* Do this just before return - we don't want to modify any rpc header
1105 data before now as we may have needed to do cryptographic actions on
1106 it before. */
1108 if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) {
1109 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1110 "setting fragment first/last ON.\n"));
1111 prhdr->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST;
1114 return NT_STATUS_OK;
1117 /****************************************************************************
1118 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1119 Normally the frag_len and buffer size will match, but on the first trans
1120 reply there is a theoretical chance that buffer size > frag_len, so we must
1121 deal with that.
1122 ****************************************************************************/
1124 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
1126 uint32 current_pdu_len = prs_data_size(current_pdu);
1128 if (current_pdu_len < prhdr->frag_len) {
1129 return NT_STATUS_BUFFER_TOO_SMALL;
1132 /* Common case. */
1133 if (current_pdu_len == (uint32)prhdr->frag_len) {
1134 prs_mem_free(current_pdu);
1135 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1136 /* Make current_pdu dynamic with no memory. */
1137 prs_give_memory(current_pdu, 0, 0, True);
1138 return NT_STATUS_OK;
1142 * Oh no ! More data in buffer than we processed in current pdu.
1143 * Cheat. Move the data down and shrink the buffer.
1146 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1147 current_pdu_len - prhdr->frag_len);
1149 /* Remember to set the read offset back to zero. */
1150 prs_set_offset(current_pdu, 0);
1152 /* Shrink the buffer. */
1153 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1154 return NT_STATUS_BUFFER_TOO_SMALL;
1157 return NT_STATUS_OK;
1160 /****************************************************************************
1161 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1162 ****************************************************************************/
1164 struct cli_api_pipe_state {
1165 struct event_context *ev;
1166 struct rpc_cli_transport *transport;
1167 uint8_t *rdata;
1168 uint32_t rdata_len;
1171 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1172 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1173 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1175 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1176 struct event_context *ev,
1177 struct rpc_cli_transport *transport,
1178 uint8_t *data, size_t data_len,
1179 uint32_t max_rdata_len)
1181 struct tevent_req *req, *subreq;
1182 struct cli_api_pipe_state *state;
1183 NTSTATUS status;
1185 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1186 if (req == NULL) {
1187 return NULL;
1189 state->ev = ev;
1190 state->transport = transport;
1192 if (max_rdata_len < RPC_HEADER_LEN) {
1194 * For a RPC reply we always need at least RPC_HEADER_LEN
1195 * bytes. We check this here because we will receive
1196 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1198 status = NT_STATUS_INVALID_PARAMETER;
1199 goto post_status;
1202 if (transport->trans_send != NULL) {
1203 subreq = transport->trans_send(state, ev, data, data_len,
1204 max_rdata_len, transport->priv);
1205 if (subreq == NULL) {
1206 goto fail;
1208 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1209 return req;
1213 * If the transport does not provide a "trans" routine, i.e. for
1214 * example the ncacn_ip_tcp transport, do the write/read step here.
1217 subreq = rpc_write_send(state, ev, transport, data, data_len);
1218 if (subreq == NULL) {
1219 goto fail;
1221 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1222 return req;
1224 status = NT_STATUS_INVALID_PARAMETER;
1226 post_status:
1227 tevent_req_nterror(req, status);
1228 return tevent_req_post(req, ev);
1229 fail:
1230 TALLOC_FREE(req);
1231 return NULL;
1234 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1236 struct tevent_req *req = tevent_req_callback_data(
1237 subreq, struct tevent_req);
1238 struct cli_api_pipe_state *state = tevent_req_data(
1239 req, struct cli_api_pipe_state);
1240 NTSTATUS status;
1242 status = state->transport->trans_recv(subreq, state, &state->rdata,
1243 &state->rdata_len);
1244 TALLOC_FREE(subreq);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 tevent_req_nterror(req, status);
1247 return;
1249 tevent_req_done(req);
1252 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1254 struct tevent_req *req = tevent_req_callback_data(
1255 subreq, struct tevent_req);
1256 struct cli_api_pipe_state *state = tevent_req_data(
1257 req, struct cli_api_pipe_state);
1258 NTSTATUS status;
1260 status = rpc_write_recv(subreq);
1261 TALLOC_FREE(subreq);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 tevent_req_nterror(req, status);
1264 return;
1267 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1268 if (tevent_req_nomem(state->rdata, req)) {
1269 return;
1273 * We don't need to use rpc_read_send here, the upper layer will cope
1274 * with a short read, transport->trans_send could also return less
1275 * than state->max_rdata_len.
1277 subreq = state->transport->read_send(state, state->ev, state->rdata,
1278 RPC_HEADER_LEN,
1279 state->transport->priv);
1280 if (tevent_req_nomem(subreq, req)) {
1281 return;
1283 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1286 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1288 struct tevent_req *req = tevent_req_callback_data(
1289 subreq, struct tevent_req);
1290 struct cli_api_pipe_state *state = tevent_req_data(
1291 req, struct cli_api_pipe_state);
1292 NTSTATUS status;
1293 ssize_t received;
1295 status = state->transport->read_recv(subreq, &received);
1296 TALLOC_FREE(subreq);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 tevent_req_nterror(req, status);
1299 return;
1301 state->rdata_len = received;
1302 tevent_req_done(req);
1305 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1306 uint8_t **prdata, uint32_t *prdata_len)
1308 struct cli_api_pipe_state *state = tevent_req_data(
1309 req, struct cli_api_pipe_state);
1310 NTSTATUS status;
1312 if (tevent_req_is_nterror(req, &status)) {
1313 return status;
1316 *prdata = talloc_move(mem_ctx, &state->rdata);
1317 *prdata_len = state->rdata_len;
1318 return NT_STATUS_OK;
1321 /****************************************************************************
1322 Send data on an rpc pipe via trans. The prs_struct data must be the last
1323 pdu fragment of an NDR data stream.
1325 Receive response data from an rpc pipe, which may be large...
1327 Read the first fragment: unfortunately have to use SMBtrans for the first
1328 bit, then SMBreadX for subsequent bits.
1330 If first fragment received also wasn't the last fragment, continue
1331 getting fragments until we _do_ receive the last fragment.
1333 Request/Response PDU's look like the following...
1335 |<------------------PDU len----------------------------------------------->|
1336 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1338 +------------+-----------------+-------------+---------------+-------------+
1339 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1340 +------------+-----------------+-------------+---------------+-------------+
1342 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1343 signing & sealing being negotiated.
1345 ****************************************************************************/
1347 struct rpc_api_pipe_state {
1348 struct event_context *ev;
1349 struct rpc_pipe_client *cli;
1350 uint8_t expected_pkt_type;
1352 prs_struct incoming_frag;
1353 struct rpc_hdr_info rhdr;
1355 prs_struct incoming_pdu; /* Incoming reply */
1356 uint32_t incoming_pdu_offset;
1359 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1361 prs_mem_free(&state->incoming_frag);
1362 prs_mem_free(&state->incoming_pdu);
1363 return 0;
1366 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1367 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1369 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1370 struct event_context *ev,
1371 struct rpc_pipe_client *cli,
1372 prs_struct *data, /* Outgoing PDU */
1373 uint8_t expected_pkt_type)
1375 struct tevent_req *req, *subreq;
1376 struct rpc_api_pipe_state *state;
1377 uint16_t max_recv_frag;
1378 NTSTATUS status;
1380 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1381 if (req == NULL) {
1382 return NULL;
1384 state->ev = ev;
1385 state->cli = cli;
1386 state->expected_pkt_type = expected_pkt_type;
1387 state->incoming_pdu_offset = 0;
1389 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1391 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1392 /* Make incoming_pdu dynamic with no memory. */
1393 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1395 talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1398 * Ensure we're not sending too much.
1400 if (prs_offset(data) > cli->max_xmit_frag) {
1401 status = NT_STATUS_INVALID_PARAMETER;
1402 goto post_status;
1405 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1407 max_recv_frag = cli->max_recv_frag;
1409 #if 0
1410 max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1411 #endif
1413 subreq = cli_api_pipe_send(state, ev, cli->transport,
1414 (uint8_t *)prs_data_p(data),
1415 prs_offset(data), max_recv_frag);
1416 if (subreq == NULL) {
1417 goto fail;
1419 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1420 return req;
1422 post_status:
1423 tevent_req_nterror(req, status);
1424 return tevent_req_post(req, ev);
1425 fail:
1426 TALLOC_FREE(req);
1427 return NULL;
1430 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1432 struct tevent_req *req = tevent_req_callback_data(
1433 subreq, struct tevent_req);
1434 struct rpc_api_pipe_state *state = tevent_req_data(
1435 req, struct rpc_api_pipe_state);
1436 NTSTATUS status;
1437 uint8_t *rdata = NULL;
1438 uint32_t rdata_len = 0;
1439 char *rdata_copy;
1441 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1442 TALLOC_FREE(subreq);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1445 tevent_req_nterror(req, status);
1446 return;
1449 if (rdata == NULL) {
1450 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1451 rpccli_pipe_txt(talloc_tos(), state->cli)));
1452 tevent_req_done(req);
1453 return;
1457 * Give the memory received from cli_trans as dynamic to the current
1458 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1459 * :-(
1461 rdata_copy = (char *)memdup(rdata, rdata_len);
1462 TALLOC_FREE(rdata);
1463 if (tevent_req_nomem(rdata_copy, req)) {
1464 return;
1466 prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
1468 /* Ensure we have enough data for a pdu. */
1469 subreq = get_complete_frag_send(state, state->ev, state->cli,
1470 &state->rhdr, &state->incoming_frag);
1471 if (tevent_req_nomem(subreq, req)) {
1472 return;
1474 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1477 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1479 struct tevent_req *req = tevent_req_callback_data(
1480 subreq, struct tevent_req);
1481 struct rpc_api_pipe_state *state = tevent_req_data(
1482 req, struct rpc_api_pipe_state);
1483 NTSTATUS status;
1484 char *rdata = NULL;
1485 uint32_t rdata_len = 0;
1487 status = get_complete_frag_recv(subreq);
1488 TALLOC_FREE(subreq);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 DEBUG(5, ("get_complete_frag failed: %s\n",
1491 nt_errstr(status)));
1492 tevent_req_nterror(req, status);
1493 return;
1496 status = cli_pipe_validate_current_pdu(
1497 state->cli, &state->rhdr, &state->incoming_frag,
1498 state->expected_pkt_type, &rdata, &rdata_len,
1499 &state->incoming_pdu);
1501 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1502 (unsigned)prs_data_size(&state->incoming_frag),
1503 (unsigned)state->incoming_pdu_offset,
1504 nt_errstr(status)));
1506 if (!NT_STATUS_IS_OK(status)) {
1507 tevent_req_nterror(req, status);
1508 return;
1511 if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST)
1512 && (state->rhdr.pack_type[0] == 0)) {
1514 * Set the data type correctly for big-endian data on the
1515 * first packet.
1517 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1518 "big-endian.\n",
1519 rpccli_pipe_txt(talloc_tos(), state->cli)));
1520 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1523 * Check endianness on subsequent packets.
1525 if (state->incoming_frag.bigendian_data
1526 != state->incoming_pdu.bigendian_data) {
1527 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1528 "%s\n",
1529 state->incoming_pdu.bigendian_data?"big":"little",
1530 state->incoming_frag.bigendian_data?"big":"little"));
1531 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1532 return;
1535 /* Now copy the data portion out of the pdu into rbuf. */
1536 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1537 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1538 return;
1541 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1542 rdata, (size_t)rdata_len);
1543 state->incoming_pdu_offset += rdata_len;
1545 status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1546 &state->incoming_frag);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 tevent_req_nterror(req, status);
1549 return;
1552 if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
1553 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1554 rpccli_pipe_txt(talloc_tos(), state->cli),
1555 (unsigned)prs_data_size(&state->incoming_pdu)));
1556 tevent_req_done(req);
1557 return;
1560 subreq = get_complete_frag_send(state, state->ev, state->cli,
1561 &state->rhdr, &state->incoming_frag);
1562 if (tevent_req_nomem(subreq, req)) {
1563 return;
1565 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1568 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1569 prs_struct *reply_pdu)
1571 struct rpc_api_pipe_state *state = tevent_req_data(
1572 req, struct rpc_api_pipe_state);
1573 NTSTATUS status;
1575 if (tevent_req_is_nterror(req, &status)) {
1576 return status;
1579 *reply_pdu = state->incoming_pdu;
1580 reply_pdu->mem_ctx = mem_ctx;
1583 * Prevent state->incoming_pdu from being freed in
1584 * rpc_api_pipe_state_destructor()
1586 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1588 return NT_STATUS_OK;
1591 /*******************************************************************
1592 Creates krb5 auth bind.
1593 ********************************************************************/
1595 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1596 enum dcerpc_AuthLevel auth_level,
1597 RPC_HDR_AUTH *pauth_out,
1598 prs_struct *auth_data)
1600 #ifdef HAVE_KRB5
1601 int ret;
1602 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1603 DATA_BLOB tkt = data_blob_null;
1604 DATA_BLOB tkt_wrapped = data_blob_null;
1606 /* We may change the pad length before marshalling. */
1607 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
1609 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1610 a->service_principal ));
1612 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1614 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1615 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1617 if (ret) {
1618 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1619 "failed with %s\n",
1620 a->service_principal,
1621 error_message(ret) ));
1623 data_blob_free(&tkt);
1624 prs_mem_free(auth_data);
1625 return NT_STATUS_INVALID_PARAMETER;
1628 /* wrap that up in a nice GSS-API wrapping */
1629 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1631 data_blob_free(&tkt);
1633 /* Auth len in the rpc header doesn't include auth_header. */
1634 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1635 data_blob_free(&tkt_wrapped);
1636 prs_mem_free(auth_data);
1637 return NT_STATUS_NO_MEMORY;
1640 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1641 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1643 data_blob_free(&tkt_wrapped);
1644 return NT_STATUS_OK;
1645 #else
1646 return NT_STATUS_INVALID_PARAMETER;
1647 #endif
1650 /*******************************************************************
1651 Creates SPNEGO NTLMSSP auth bind.
1652 ********************************************************************/
1654 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1655 enum dcerpc_AuthLevel auth_level,
1656 RPC_HDR_AUTH *pauth_out,
1657 prs_struct *auth_data)
1659 NTSTATUS nt_status;
1660 DATA_BLOB null_blob = data_blob_null;
1661 DATA_BLOB request = data_blob_null;
1662 DATA_BLOB spnego_msg = data_blob_null;
1664 /* We may change the pad length before marshalling. */
1665 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
1667 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1668 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1669 null_blob,
1670 &request);
1672 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1673 data_blob_free(&request);
1674 prs_mem_free(auth_data);
1675 return nt_status;
1678 /* Wrap this in SPNEGO. */
1679 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1681 data_blob_free(&request);
1683 /* Auth len in the rpc header doesn't include auth_header. */
1684 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1685 data_blob_free(&spnego_msg);
1686 prs_mem_free(auth_data);
1687 return NT_STATUS_NO_MEMORY;
1690 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1691 dump_data(5, spnego_msg.data, spnego_msg.length);
1693 data_blob_free(&spnego_msg);
1694 return NT_STATUS_OK;
1697 /*******************************************************************
1698 Creates NTLMSSP auth bind.
1699 ********************************************************************/
1701 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1702 enum dcerpc_AuthLevel auth_level,
1703 RPC_HDR_AUTH *pauth_out,
1704 prs_struct *auth_data)
1706 NTSTATUS nt_status;
1707 DATA_BLOB null_blob = data_blob_null;
1708 DATA_BLOB request = data_blob_null;
1710 /* We may change the pad length before marshalling. */
1711 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
1713 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1714 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1715 null_blob,
1716 &request);
1718 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1719 data_blob_free(&request);
1720 prs_mem_free(auth_data);
1721 return nt_status;
1724 /* Auth len in the rpc header doesn't include auth_header. */
1725 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1726 data_blob_free(&request);
1727 prs_mem_free(auth_data);
1728 return NT_STATUS_NO_MEMORY;
1731 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1732 dump_data(5, request.data, request.length);
1734 data_blob_free(&request);
1735 return NT_STATUS_OK;
1738 /*******************************************************************
1739 Creates schannel auth bind.
1740 ********************************************************************/
1742 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1743 enum dcerpc_AuthLevel auth_level,
1744 RPC_HDR_AUTH *pauth_out,
1745 prs_struct *auth_data)
1747 struct NL_AUTH_MESSAGE r;
1748 enum ndr_err_code ndr_err;
1749 DATA_BLOB blob;
1751 /* We may change the pad length before marshalling. */
1752 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
1754 /* Use lp_workgroup() if domain not specified */
1756 if (!cli->auth->domain || !cli->auth->domain[0]) {
1757 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1758 if (cli->auth->domain == NULL) {
1759 return NT_STATUS_NO_MEMORY;
1764 * Now marshall the data into the auth parse_struct.
1767 r.MessageType = NL_NEGOTIATE_REQUEST;
1768 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1769 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1770 r.oem_netbios_domain.a = cli->auth->domain;
1771 r.oem_netbios_computer.a = global_myname();
1773 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &r,
1774 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
1775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1776 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1777 prs_mem_free(auth_data);
1778 return ndr_map_error2ntstatus(ndr_err);
1781 if (DEBUGLEVEL >= 10) {
1782 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
1785 if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
1787 prs_mem_free(auth_data);
1788 return NT_STATUS_NO_MEMORY;
1791 return NT_STATUS_OK;
1794 /*******************************************************************
1795 Creates the internals of a DCE/RPC bind request or alter context PDU.
1796 ********************************************************************/
1798 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type,
1799 prs_struct *rpc_out,
1800 uint32 rpc_call_id,
1801 const struct ndr_syntax_id *abstract,
1802 const struct ndr_syntax_id *transfer,
1803 RPC_HDR_AUTH *phdr_auth,
1804 prs_struct *pauth_info)
1806 RPC_HDR hdr;
1807 RPC_HDR_RB hdr_rb;
1808 RPC_CONTEXT rpc_ctx;
1809 uint16 auth_len = prs_offset(pauth_info);
1810 uint8 ss_padding_len = 0;
1811 uint16 frag_len = 0;
1813 /* create the RPC context. */
1814 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1816 /* create the bind request RPC_HDR_RB */
1817 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1819 /* Start building the frag length. */
1820 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1822 /* Do we need to pad ? */
1823 if (auth_len) {
1824 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1825 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1826 ss_padding_len = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1827 phdr_auth->auth_pad_len = ss_padding_len;
1829 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1832 /* Create the request RPC_HDR */
1833 init_rpc_hdr(&hdr, pkt_type, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id, frag_len, auth_len);
1835 /* Marshall the RPC header */
1836 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1837 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1838 return NT_STATUS_NO_MEMORY;
1841 /* Marshall the bind request data */
1842 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1843 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1844 return NT_STATUS_NO_MEMORY;
1848 * Grow the outgoing buffer to store any auth info.
1851 if(auth_len != 0) {
1852 if (ss_padding_len) {
1853 char pad[CLIENT_NDR_PADDING_SIZE];
1854 memset(pad, '\0', CLIENT_NDR_PADDING_SIZE);
1855 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1856 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1857 return NT_STATUS_NO_MEMORY;
1861 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1862 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1863 return NT_STATUS_NO_MEMORY;
1867 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1868 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1869 return NT_STATUS_NO_MEMORY;
1873 return NT_STATUS_OK;
1876 /*******************************************************************
1877 Creates a DCE/RPC bind request.
1878 ********************************************************************/
1880 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1881 prs_struct *rpc_out,
1882 uint32 rpc_call_id,
1883 const struct ndr_syntax_id *abstract,
1884 const struct ndr_syntax_id *transfer,
1885 enum pipe_auth_type auth_type,
1886 enum dcerpc_AuthLevel auth_level)
1888 RPC_HDR_AUTH hdr_auth;
1889 prs_struct auth_info;
1890 NTSTATUS ret = NT_STATUS_OK;
1892 ZERO_STRUCT(hdr_auth);
1893 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1894 return NT_STATUS_NO_MEMORY;
1896 switch (auth_type) {
1897 case PIPE_AUTH_TYPE_SCHANNEL:
1898 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1899 if (!NT_STATUS_IS_OK(ret)) {
1900 prs_mem_free(&auth_info);
1901 return ret;
1903 break;
1905 case PIPE_AUTH_TYPE_NTLMSSP:
1906 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1907 if (!NT_STATUS_IS_OK(ret)) {
1908 prs_mem_free(&auth_info);
1909 return ret;
1911 break;
1913 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1914 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1915 if (!NT_STATUS_IS_OK(ret)) {
1916 prs_mem_free(&auth_info);
1917 return ret;
1919 break;
1921 case PIPE_AUTH_TYPE_KRB5:
1922 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1923 if (!NT_STATUS_IS_OK(ret)) {
1924 prs_mem_free(&auth_info);
1925 return ret;
1927 break;
1929 case PIPE_AUTH_TYPE_NONE:
1930 break;
1932 default:
1933 /* "Can't" happen. */
1934 return NT_STATUS_INVALID_INFO_CLASS;
1937 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1938 rpc_out,
1939 rpc_call_id,
1940 abstract,
1941 transfer,
1942 &hdr_auth,
1943 &auth_info);
1945 prs_mem_free(&auth_info);
1946 return ret;
1949 /*******************************************************************
1950 Create and add the NTLMSSP sign/seal auth header and data.
1951 ********************************************************************/
1953 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1954 RPC_HDR *phdr,
1955 uint32 ss_padding_len,
1956 prs_struct *outgoing_pdu)
1958 RPC_HDR_AUTH auth_info;
1959 NTSTATUS status;
1960 DATA_BLOB auth_blob = data_blob_null;
1961 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1963 if (!cli->auth->a_u.ntlmssp_state) {
1964 return NT_STATUS_INVALID_PARAMETER;
1967 /* Init and marshall the auth header. */
1968 init_rpc_hdr_auth(&auth_info,
1969 map_pipe_auth_type_to_rpc_auth_type(
1970 cli->auth->auth_type),
1971 cli->auth->auth_level,
1972 ss_padding_len,
1973 1 /* context id. */);
1975 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1976 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1977 data_blob_free(&auth_blob);
1978 return NT_STATUS_NO_MEMORY;
1981 switch (cli->auth->auth_level) {
1982 case DCERPC_AUTH_LEVEL_PRIVACY:
1983 /* Data portion is encrypted. */
1984 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1985 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1986 data_and_pad_len,
1987 (unsigned char *)prs_data_p(outgoing_pdu),
1988 (size_t)prs_offset(outgoing_pdu),
1989 &auth_blob);
1990 if (!NT_STATUS_IS_OK(status)) {
1991 data_blob_free(&auth_blob);
1992 return status;
1994 break;
1996 case DCERPC_AUTH_LEVEL_INTEGRITY:
1997 /* Data is signed. */
1998 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1999 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
2000 data_and_pad_len,
2001 (unsigned char *)prs_data_p(outgoing_pdu),
2002 (size_t)prs_offset(outgoing_pdu),
2003 &auth_blob);
2004 if (!NT_STATUS_IS_OK(status)) {
2005 data_blob_free(&auth_blob);
2006 return status;
2008 break;
2010 default:
2011 /* Can't happen. */
2012 smb_panic("bad auth level");
2013 /* Notreached. */
2014 return NT_STATUS_INVALID_PARAMETER;
2017 /* Finally marshall the blob. */
2019 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
2020 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
2021 (unsigned int)NTLMSSP_SIG_SIZE));
2022 data_blob_free(&auth_blob);
2023 return NT_STATUS_NO_MEMORY;
2026 data_blob_free(&auth_blob);
2027 return NT_STATUS_OK;
2030 /*******************************************************************
2031 Create and add the schannel sign/seal auth header and data.
2032 ********************************************************************/
2034 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2035 RPC_HDR *phdr,
2036 uint32 ss_padding_len,
2037 prs_struct *outgoing_pdu)
2039 RPC_HDR_AUTH auth_info;
2040 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2041 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2042 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2043 DATA_BLOB blob;
2044 NTSTATUS status;
2046 if (!sas) {
2047 return NT_STATUS_INVALID_PARAMETER;
2050 /* Init and marshall the auth header. */
2051 init_rpc_hdr_auth(&auth_info,
2052 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2053 cli->auth->auth_level,
2054 ss_padding_len,
2055 1 /* context id. */);
2057 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
2058 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
2059 return NT_STATUS_NO_MEMORY;
2062 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2063 sas->seq_num));
2065 switch (cli->auth->auth_level) {
2066 case DCERPC_AUTH_LEVEL_PRIVACY:
2067 status = netsec_outgoing_packet(sas,
2068 talloc_tos(),
2069 true,
2070 (uint8_t *)data_p,
2071 data_and_pad_len,
2072 &blob);
2073 break;
2074 case DCERPC_AUTH_LEVEL_INTEGRITY:
2075 status = netsec_outgoing_packet(sas,
2076 talloc_tos(),
2077 false,
2078 (uint8_t *)data_p,
2079 data_and_pad_len,
2080 &blob);
2081 break;
2082 default:
2083 status = NT_STATUS_INTERNAL_ERROR;
2084 break;
2087 if (!NT_STATUS_IS_OK(status)) {
2088 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2089 nt_errstr(status)));
2090 return status;
2093 if (DEBUGLEVEL >= 10) {
2094 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2097 /* Finally marshall the blob. */
2098 if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
2099 return NT_STATUS_NO_MEMORY;
2102 return NT_STATUS_OK;
2105 /*******************************************************************
2106 Calculate how much data we're going to send in this packet, also
2107 work out any sign/seal padding length.
2108 ********************************************************************/
2110 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2111 uint32 data_left,
2112 uint16 *p_frag_len,
2113 uint16 *p_auth_len,
2114 uint32 *p_ss_padding)
2116 uint32 data_space, data_len;
2118 #if 0
2119 if ((data_left > 0) && (sys_random() % 2)) {
2120 data_left = MAX(data_left/2, 1);
2122 #endif
2124 switch (cli->auth->auth_level) {
2125 case DCERPC_AUTH_LEVEL_NONE:
2126 case DCERPC_AUTH_LEVEL_CONNECT:
2127 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2128 data_len = MIN(data_space, data_left);
2129 *p_ss_padding = 0;
2130 *p_auth_len = 0;
2131 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2132 return data_len;
2134 case DCERPC_AUTH_LEVEL_INTEGRITY:
2135 case DCERPC_AUTH_LEVEL_PRIVACY:
2136 /* Treat the same for all authenticated rpc requests. */
2137 switch(cli->auth->auth_type) {
2138 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2139 case PIPE_AUTH_TYPE_NTLMSSP:
2140 *p_auth_len = NTLMSSP_SIG_SIZE;
2141 break;
2142 case PIPE_AUTH_TYPE_SCHANNEL:
2143 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2144 break;
2145 default:
2146 smb_panic("bad auth type");
2147 break;
2150 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2151 RPC_HDR_AUTH_LEN - *p_auth_len;
2153 data_len = MIN(data_space, data_left);
2154 *p_ss_padding = 0;
2155 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2156 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2158 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
2159 data_len + *p_ss_padding + /* data plus padding. */
2160 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
2161 return data_len;
2163 default:
2164 smb_panic("bad auth level");
2165 /* Notreached. */
2166 return 0;
2170 /*******************************************************************
2171 External interface.
2172 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2173 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2174 and deals with signing/sealing details.
2175 ********************************************************************/
2177 struct rpc_api_pipe_req_state {
2178 struct event_context *ev;
2179 struct rpc_pipe_client *cli;
2180 uint8_t op_num;
2181 uint32_t call_id;
2182 prs_struct *req_data;
2183 uint32_t req_data_sent;
2184 prs_struct outgoing_frag;
2185 prs_struct reply_pdu;
2188 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2190 prs_mem_free(&s->outgoing_frag);
2191 prs_mem_free(&s->reply_pdu);
2192 return 0;
2195 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2196 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2197 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2198 bool *is_last_frag);
2200 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2201 struct event_context *ev,
2202 struct rpc_pipe_client *cli,
2203 uint8_t op_num,
2204 prs_struct *req_data)
2206 struct tevent_req *req, *subreq;
2207 struct rpc_api_pipe_req_state *state;
2208 NTSTATUS status;
2209 bool is_last_frag;
2211 req = tevent_req_create(mem_ctx, &state,
2212 struct rpc_api_pipe_req_state);
2213 if (req == NULL) {
2214 return NULL;
2216 state->ev = ev;
2217 state->cli = cli;
2218 state->op_num = op_num;
2219 state->req_data = req_data;
2220 state->req_data_sent = 0;
2221 state->call_id = get_rpc_call_id();
2223 if (cli->max_xmit_frag
2224 < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2225 /* Server is screwed up ! */
2226 status = NT_STATUS_INVALID_PARAMETER;
2227 goto post_status;
2230 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2232 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2233 state, MARSHALL)) {
2234 goto fail;
2237 talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2239 status = prepare_next_frag(state, &is_last_frag);
2240 if (!NT_STATUS_IS_OK(status)) {
2241 goto post_status;
2244 if (is_last_frag) {
2245 subreq = rpc_api_pipe_send(state, ev, state->cli,
2246 &state->outgoing_frag,
2247 DCERPC_PKT_RESPONSE);
2248 if (subreq == NULL) {
2249 goto fail;
2251 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2252 } else {
2253 subreq = rpc_write_send(
2254 state, ev, cli->transport,
2255 (uint8_t *)prs_data_p(&state->outgoing_frag),
2256 prs_offset(&state->outgoing_frag));
2257 if (subreq == NULL) {
2258 goto fail;
2260 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2261 req);
2263 return req;
2265 post_status:
2266 tevent_req_nterror(req, status);
2267 return tevent_req_post(req, ev);
2268 fail:
2269 TALLOC_FREE(req);
2270 return NULL;
2273 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2274 bool *is_last_frag)
2276 RPC_HDR hdr;
2277 RPC_HDR_REQ hdr_req;
2278 uint32_t data_sent_thistime;
2279 uint16_t auth_len;
2280 uint16_t frag_len;
2281 uint8_t flags = 0;
2282 uint32_t ss_padding;
2283 uint32_t data_left;
2284 char pad[8] = { 0, };
2285 NTSTATUS status;
2287 data_left = prs_offset(state->req_data) - state->req_data_sent;
2289 data_sent_thistime = calculate_data_len_tosend(
2290 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2292 if (state->req_data_sent == 0) {
2293 flags = DCERPC_PFC_FLAG_FIRST;
2296 if (data_sent_thistime == data_left) {
2297 flags |= DCERPC_PFC_FLAG_LAST;
2300 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2301 return NT_STATUS_NO_MEMORY;
2304 /* Create and marshall the header and request header. */
2305 init_rpc_hdr(&hdr, DCERPC_PKT_REQUEST, flags, state->call_id, frag_len,
2306 auth_len);
2308 if (!smb_io_rpc_hdr("hdr ", &hdr, &state->outgoing_frag, 0)) {
2309 return NT_STATUS_NO_MEMORY;
2312 /* Create the rpc request RPC_HDR_REQ */
2313 init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2314 state->op_num);
2316 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2317 &state->outgoing_frag, 0)) {
2318 return NT_STATUS_NO_MEMORY;
2321 /* Copy in the data, plus any ss padding. */
2322 if (!prs_append_some_prs_data(&state->outgoing_frag,
2323 state->req_data, state->req_data_sent,
2324 data_sent_thistime)) {
2325 return NT_STATUS_NO_MEMORY;
2328 /* Copy the sign/seal padding data. */
2329 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2330 return NT_STATUS_NO_MEMORY;
2333 /* Generate any auth sign/seal and add the auth footer. */
2334 switch (state->cli->auth->auth_type) {
2335 case PIPE_AUTH_TYPE_NONE:
2336 status = NT_STATUS_OK;
2337 break;
2338 case PIPE_AUTH_TYPE_NTLMSSP:
2339 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2340 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2341 &state->outgoing_frag);
2342 break;
2343 case PIPE_AUTH_TYPE_SCHANNEL:
2344 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2345 &state->outgoing_frag);
2346 break;
2347 default:
2348 status = NT_STATUS_INVALID_PARAMETER;
2349 break;
2352 state->req_data_sent += data_sent_thistime;
2353 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2355 return status;
2358 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2360 struct tevent_req *req = tevent_req_callback_data(
2361 subreq, struct tevent_req);
2362 struct rpc_api_pipe_req_state *state = tevent_req_data(
2363 req, struct rpc_api_pipe_req_state);
2364 NTSTATUS status;
2365 bool is_last_frag;
2367 status = rpc_write_recv(subreq);
2368 TALLOC_FREE(subreq);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 tevent_req_nterror(req, status);
2371 return;
2374 status = prepare_next_frag(state, &is_last_frag);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 tevent_req_nterror(req, status);
2377 return;
2380 if (is_last_frag) {
2381 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2382 &state->outgoing_frag,
2383 DCERPC_PKT_RESPONSE);
2384 if (tevent_req_nomem(subreq, req)) {
2385 return;
2387 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2388 } else {
2389 subreq = rpc_write_send(
2390 state, state->ev,
2391 state->cli->transport,
2392 (uint8_t *)prs_data_p(&state->outgoing_frag),
2393 prs_offset(&state->outgoing_frag));
2394 if (tevent_req_nomem(subreq, req)) {
2395 return;
2397 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2398 req);
2402 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2404 struct tevent_req *req = tevent_req_callback_data(
2405 subreq, struct tevent_req);
2406 struct rpc_api_pipe_req_state *state = tevent_req_data(
2407 req, struct rpc_api_pipe_req_state);
2408 NTSTATUS status;
2410 status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2411 TALLOC_FREE(subreq);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 tevent_req_nterror(req, status);
2414 return;
2416 tevent_req_done(req);
2419 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2420 prs_struct *reply_pdu)
2422 struct rpc_api_pipe_req_state *state = tevent_req_data(
2423 req, struct rpc_api_pipe_req_state);
2424 NTSTATUS status;
2426 if (tevent_req_is_nterror(req, &status)) {
2428 * We always have to initialize to reply pdu, even if there is
2429 * none. The rpccli_* caller routines expect this.
2431 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2432 return status;
2435 *reply_pdu = state->reply_pdu;
2436 reply_pdu->mem_ctx = mem_ctx;
2439 * Prevent state->req_pdu from being freed in
2440 * rpc_api_pipe_req_state_destructor()
2442 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2444 return NT_STATUS_OK;
2447 #if 0
2448 /****************************************************************************
2449 Set the handle state.
2450 ****************************************************************************/
2452 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2453 const char *pipe_name, uint16 device_state)
2455 bool state_set = False;
2456 char param[2];
2457 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2458 char *rparam = NULL;
2459 char *rdata = NULL;
2460 uint32 rparam_len, rdata_len;
2462 if (pipe_name == NULL)
2463 return False;
2465 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2466 cli->fnum, pipe_name, device_state));
2468 /* create parameters: device state */
2469 SSVAL(param, 0, device_state);
2471 /* create setup parameters. */
2472 setup[0] = 0x0001;
2473 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2475 /* send the data on \PIPE\ */
2476 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2477 setup, 2, 0, /* setup, length, max */
2478 param, 2, 0, /* param, length, max */
2479 NULL, 0, 1024, /* data, length, max */
2480 &rparam, &rparam_len, /* return param, length */
2481 &rdata, &rdata_len)) /* return data, length */
2483 DEBUG(5, ("Set Handle state: return OK\n"));
2484 state_set = True;
2487 SAFE_FREE(rparam);
2488 SAFE_FREE(rdata);
2490 return state_set;
2492 #endif
2494 /****************************************************************************
2495 Check the rpc bind acknowledge response.
2496 ****************************************************************************/
2498 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2499 const struct ndr_syntax_id *transfer)
2501 if ( hdr_ba->addr.len == 0) {
2502 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2505 /* check the transfer syntax */
2506 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2507 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2508 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2509 return False;
2512 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2513 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2514 hdr_ba->res.num_results, hdr_ba->res.reason));
2517 DEBUG(5,("check_bind_response: accepted!\n"));
2518 return True;
2521 /*******************************************************************
2522 Creates a DCE/RPC bind authentication response.
2523 This is the packet that is sent back to the server once we
2524 have received a BIND-ACK, to finish the third leg of
2525 the authentication handshake.
2526 ********************************************************************/
2528 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2529 uint32 rpc_call_id,
2530 enum pipe_auth_type auth_type,
2531 enum dcerpc_AuthLevel auth_level,
2532 DATA_BLOB *pauth_blob,
2533 prs_struct *rpc_out)
2535 RPC_HDR hdr;
2536 RPC_HDR_AUTH hdr_auth;
2537 uint32 pad = 0;
2539 /* Create the request RPC_HDR */
2540 init_rpc_hdr(&hdr, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id,
2541 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2542 pauth_blob->length );
2544 /* Marshall it. */
2545 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2546 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2547 return NT_STATUS_NO_MEMORY;
2551 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2552 about padding - shouldn't this pad to length CLIENT_NDR_PADDING_SIZE ? JRA.
2555 /* 4 bytes padding. */
2556 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2557 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2558 return NT_STATUS_NO_MEMORY;
2561 /* Create the request RPC_HDR_AUTHA */
2562 init_rpc_hdr_auth(&hdr_auth,
2563 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2564 auth_level, 0, 1);
2566 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2567 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2568 return NT_STATUS_NO_MEMORY;
2572 * Append the auth data to the outgoing buffer.
2575 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2576 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2577 return NT_STATUS_NO_MEMORY;
2580 return NT_STATUS_OK;
2583 /*******************************************************************
2584 Creates a DCE/RPC bind alter context authentication request which
2585 may contain a spnego auth blobl
2586 ********************************************************************/
2588 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2589 const struct ndr_syntax_id *abstract,
2590 const struct ndr_syntax_id *transfer,
2591 enum dcerpc_AuthLevel auth_level,
2592 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2593 prs_struct *rpc_out)
2595 RPC_HDR_AUTH hdr_auth;
2596 prs_struct auth_info;
2597 NTSTATUS ret = NT_STATUS_OK;
2599 ZERO_STRUCT(hdr_auth);
2600 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2601 return NT_STATUS_NO_MEMORY;
2603 /* We may change the pad length before marshalling. */
2604 init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
2606 if (pauth_blob->length) {
2607 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2608 prs_mem_free(&auth_info);
2609 return NT_STATUS_NO_MEMORY;
2613 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2614 rpc_out,
2615 rpc_call_id,
2616 abstract,
2617 transfer,
2618 &hdr_auth,
2619 &auth_info);
2620 prs_mem_free(&auth_info);
2621 return ret;
2624 /****************************************************************************
2625 Do an rpc bind.
2626 ****************************************************************************/
2628 struct rpc_pipe_bind_state {
2629 struct event_context *ev;
2630 struct rpc_pipe_client *cli;
2631 prs_struct rpc_out;
2632 uint32_t rpc_call_id;
2635 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2637 prs_mem_free(&state->rpc_out);
2638 return 0;
2641 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2642 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2643 struct rpc_pipe_bind_state *state,
2644 struct rpc_hdr_info *phdr,
2645 prs_struct *reply_pdu);
2646 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2647 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2648 struct rpc_pipe_bind_state *state,
2649 struct rpc_hdr_info *phdr,
2650 prs_struct *reply_pdu);
2651 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2653 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2654 struct event_context *ev,
2655 struct rpc_pipe_client *cli,
2656 struct cli_pipe_auth_data *auth)
2658 struct tevent_req *req, *subreq;
2659 struct rpc_pipe_bind_state *state;
2660 NTSTATUS status;
2662 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2663 if (req == NULL) {
2664 return NULL;
2667 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2668 rpccli_pipe_txt(talloc_tos(), cli),
2669 (unsigned int)auth->auth_type,
2670 (unsigned int)auth->auth_level ));
2672 state->ev = ev;
2673 state->cli = cli;
2674 state->rpc_call_id = get_rpc_call_id();
2676 prs_init_empty(&state->rpc_out, state, MARSHALL);
2677 talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2679 cli->auth = talloc_move(cli, &auth);
2681 /* Marshall the outgoing data. */
2682 status = create_rpc_bind_req(cli, &state->rpc_out,
2683 state->rpc_call_id,
2684 &cli->abstract_syntax,
2685 &cli->transfer_syntax,
2686 cli->auth->auth_type,
2687 cli->auth->auth_level);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 goto post_status;
2693 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2694 DCERPC_PKT_BIND_ACK);
2695 if (subreq == NULL) {
2696 goto fail;
2698 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2699 return req;
2701 post_status:
2702 tevent_req_nterror(req, status);
2703 return tevent_req_post(req, ev);
2704 fail:
2705 TALLOC_FREE(req);
2706 return NULL;
2709 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2711 struct tevent_req *req = tevent_req_callback_data(
2712 subreq, struct tevent_req);
2713 struct rpc_pipe_bind_state *state = tevent_req_data(
2714 req, struct rpc_pipe_bind_state);
2715 prs_struct reply_pdu;
2716 struct rpc_hdr_info hdr;
2717 struct rpc_hdr_ba_info hdr_ba;
2718 NTSTATUS status;
2720 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2721 TALLOC_FREE(subreq);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2724 rpccli_pipe_txt(talloc_tos(), state->cli),
2725 nt_errstr(status)));
2726 tevent_req_nterror(req, status);
2727 return;
2730 /* Unmarshall the RPC header */
2731 if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2732 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2733 prs_mem_free(&reply_pdu);
2734 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2735 return;
2738 if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2739 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2740 "RPC_HDR_BA.\n"));
2741 prs_mem_free(&reply_pdu);
2742 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2743 return;
2746 if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2747 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2748 prs_mem_free(&reply_pdu);
2749 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2750 return;
2753 state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2754 state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2757 * For authenticated binds we may need to do 3 or 4 leg binds.
2760 switch(state->cli->auth->auth_type) {
2762 case PIPE_AUTH_TYPE_NONE:
2763 case PIPE_AUTH_TYPE_SCHANNEL:
2764 /* Bind complete. */
2765 prs_mem_free(&reply_pdu);
2766 tevent_req_done(req);
2767 break;
2769 case PIPE_AUTH_TYPE_NTLMSSP:
2770 /* Need to send AUTH3 packet - no reply. */
2771 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2772 &reply_pdu);
2773 prs_mem_free(&reply_pdu);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 tevent_req_nterror(req, status);
2777 break;
2779 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2780 /* Need to send alter context request and reply. */
2781 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2782 &reply_pdu);
2783 prs_mem_free(&reply_pdu);
2784 if (!NT_STATUS_IS_OK(status)) {
2785 tevent_req_nterror(req, status);
2787 break;
2789 case PIPE_AUTH_TYPE_KRB5:
2790 /* */
2792 default:
2793 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2794 (unsigned int)state->cli->auth->auth_type));
2795 prs_mem_free(&reply_pdu);
2796 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2800 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2801 struct rpc_pipe_bind_state *state,
2802 struct rpc_hdr_info *phdr,
2803 prs_struct *reply_pdu)
2805 DATA_BLOB server_response = data_blob_null;
2806 DATA_BLOB client_reply = data_blob_null;
2807 struct rpc_hdr_auth_info hdr_auth;
2808 struct tevent_req *subreq;
2809 NTSTATUS status;
2811 if ((phdr->auth_len == 0)
2812 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2813 return NT_STATUS_INVALID_PARAMETER;
2816 if (!prs_set_offset(
2817 reply_pdu,
2818 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2819 return NT_STATUS_INVALID_PARAMETER;
2822 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2823 return NT_STATUS_INVALID_PARAMETER;
2826 /* TODO - check auth_type/auth_level match. */
2828 server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2829 prs_copy_data_out((char *)server_response.data, reply_pdu,
2830 phdr->auth_len);
2832 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2833 server_response, &client_reply);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2837 "blob failed: %s.\n", nt_errstr(status)));
2838 return status;
2841 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2843 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2844 state->cli->auth->auth_type,
2845 state->cli->auth->auth_level,
2846 &client_reply, &state->rpc_out);
2847 data_blob_free(&client_reply);
2849 if (!NT_STATUS_IS_OK(status)) {
2850 return status;
2853 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2854 (uint8_t *)prs_data_p(&state->rpc_out),
2855 prs_offset(&state->rpc_out));
2856 if (subreq == NULL) {
2857 return NT_STATUS_NO_MEMORY;
2859 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2860 return NT_STATUS_OK;
2863 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2865 struct tevent_req *req = tevent_req_callback_data(
2866 subreq, struct tevent_req);
2867 NTSTATUS status;
2869 status = rpc_write_recv(subreq);
2870 TALLOC_FREE(subreq);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 tevent_req_nterror(req, status);
2873 return;
2875 tevent_req_done(req);
2878 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2879 struct rpc_pipe_bind_state *state,
2880 struct rpc_hdr_info *phdr,
2881 prs_struct *reply_pdu)
2883 DATA_BLOB server_spnego_response = data_blob_null;
2884 DATA_BLOB server_ntlm_response = data_blob_null;
2885 DATA_BLOB client_reply = data_blob_null;
2886 DATA_BLOB tmp_blob = data_blob_null;
2887 RPC_HDR_AUTH hdr_auth;
2888 struct tevent_req *subreq;
2889 NTSTATUS status;
2891 if ((phdr->auth_len == 0)
2892 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2893 return NT_STATUS_INVALID_PARAMETER;
2896 /* Process the returned NTLMSSP blob first. */
2897 if (!prs_set_offset(
2898 reply_pdu,
2899 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2900 return NT_STATUS_INVALID_PARAMETER;
2903 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2904 return NT_STATUS_INVALID_PARAMETER;
2907 server_spnego_response = data_blob(NULL, phdr->auth_len);
2908 prs_copy_data_out((char *)server_spnego_response.data,
2909 reply_pdu, phdr->auth_len);
2912 * The server might give us back two challenges - tmp_blob is for the
2913 * second.
2915 if (!spnego_parse_challenge(server_spnego_response,
2916 &server_ntlm_response, &tmp_blob)) {
2917 data_blob_free(&server_spnego_response);
2918 data_blob_free(&server_ntlm_response);
2919 data_blob_free(&tmp_blob);
2920 return NT_STATUS_INVALID_PARAMETER;
2923 /* We're finished with the server spnego response and the tmp_blob. */
2924 data_blob_free(&server_spnego_response);
2925 data_blob_free(&tmp_blob);
2927 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2928 server_ntlm_response, &client_reply);
2930 /* Finished with the server_ntlm response */
2931 data_blob_free(&server_ntlm_response);
2933 if (!NT_STATUS_IS_OK(status)) {
2934 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2935 "using server blob failed.\n"));
2936 data_blob_free(&client_reply);
2937 return status;
2940 /* SPNEGO wrap the client reply. */
2941 tmp_blob = spnego_gen_auth(client_reply);
2942 data_blob_free(&client_reply);
2943 client_reply = tmp_blob;
2944 tmp_blob = data_blob_null;
2946 /* Now prepare the alter context pdu. */
2947 prs_init_empty(&state->rpc_out, state, MARSHALL);
2949 status = create_rpc_alter_context(state->rpc_call_id,
2950 &state->cli->abstract_syntax,
2951 &state->cli->transfer_syntax,
2952 state->cli->auth->auth_level,
2953 &client_reply,
2954 &state->rpc_out);
2955 data_blob_free(&client_reply);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 return status;
2961 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2962 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2963 if (subreq == NULL) {
2964 return NT_STATUS_NO_MEMORY;
2966 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2967 return NT_STATUS_OK;
2970 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2972 struct tevent_req *req = tevent_req_callback_data(
2973 subreq, struct tevent_req);
2974 struct rpc_pipe_bind_state *state = tevent_req_data(
2975 req, struct rpc_pipe_bind_state);
2976 DATA_BLOB server_spnego_response = data_blob_null;
2977 DATA_BLOB tmp_blob = data_blob_null;
2978 prs_struct reply_pdu;
2979 struct rpc_hdr_info hdr;
2980 struct rpc_hdr_auth_info hdr_auth;
2981 NTSTATUS status;
2983 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2984 TALLOC_FREE(subreq);
2985 if (!NT_STATUS_IS_OK(status)) {
2986 tevent_req_nterror(req, status);
2987 return;
2990 /* Get the auth blob from the reply. */
2991 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) {
2992 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
2993 "unmarshall RPC_HDR.\n"));
2994 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2995 return;
2998 if (!prs_set_offset(
2999 &reply_pdu,
3000 hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
3001 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3002 return;
3005 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
3006 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3007 return;
3010 server_spnego_response = data_blob(NULL, hdr.auth_len);
3011 prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
3012 hdr.auth_len);
3014 /* Check we got a valid auth response. */
3015 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
3016 OID_NTLMSSP, &tmp_blob)) {
3017 data_blob_free(&server_spnego_response);
3018 data_blob_free(&tmp_blob);
3019 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3020 return;
3023 data_blob_free(&server_spnego_response);
3024 data_blob_free(&tmp_blob);
3026 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
3027 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
3028 tevent_req_done(req);
3031 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3033 return tevent_req_simple_recv_ntstatus(req);
3036 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3037 struct cli_pipe_auth_data *auth)
3039 TALLOC_CTX *frame = talloc_stackframe();
3040 struct event_context *ev;
3041 struct tevent_req *req;
3042 NTSTATUS status = NT_STATUS_OK;
3044 ev = event_context_init(frame);
3045 if (ev == NULL) {
3046 status = NT_STATUS_NO_MEMORY;
3047 goto fail;
3050 req = rpc_pipe_bind_send(frame, ev, cli, auth);
3051 if (req == NULL) {
3052 status = NT_STATUS_NO_MEMORY;
3053 goto fail;
3056 if (!tevent_req_poll(req, ev)) {
3057 status = map_nt_error_from_unix(errno);
3058 goto fail;
3061 status = rpc_pipe_bind_recv(req);
3062 fail:
3063 TALLOC_FREE(frame);
3064 return status;
3067 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3068 unsigned int timeout)
3070 struct cli_state *cli;
3072 if (rpc_cli->transport->transport == NCACN_NP) {
3073 cli = rpc_pipe_np_smb_conn(rpc_cli);
3074 if (cli == NULL) {
3075 return 0;
3077 return cli_set_timeout(cli, timeout);
3080 if (rpc_cli->transport->transport == NCACN_IP_TCP ||
3081 rpc_cli->transport->transport == NCALRPC) {
3082 return rpccli_set_sock_timeout(rpc_cli, timeout);
3085 if (rpc_cli->transport->transport == NCACN_INTERNAL) {
3086 cli = rpc_pipe_smbd_smb_conn(rpc_cli);
3087 if (!cli) {
3088 return 0;
3090 return cli_set_timeout(cli, timeout);
3093 return 0;
3096 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3098 struct cli_state *cli;
3100 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3101 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3102 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3103 return true;
3106 cli = rpc_pipe_np_smb_conn(rpc_cli);
3107 if (cli == NULL) {
3108 return false;
3110 E_md4hash(cli->password ? cli->password : "", nt_hash);
3111 return true;
3114 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3115 struct cli_pipe_auth_data **presult)
3117 struct cli_pipe_auth_data *result;
3119 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3120 if (result == NULL) {
3121 return NT_STATUS_NO_MEMORY;
3124 result->auth_type = PIPE_AUTH_TYPE_NONE;
3125 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3127 result->user_name = talloc_strdup(result, "");
3128 result->domain = talloc_strdup(result, "");
3129 if ((result->user_name == NULL) || (result->domain == NULL)) {
3130 TALLOC_FREE(result);
3131 return NT_STATUS_NO_MEMORY;
3134 *presult = result;
3135 return NT_STATUS_OK;
3138 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3140 ntlmssp_end(&auth->a_u.ntlmssp_state);
3141 return 0;
3144 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3145 enum pipe_auth_type auth_type,
3146 enum dcerpc_AuthLevel auth_level,
3147 const char *domain,
3148 const char *username,
3149 const char *password,
3150 struct cli_pipe_auth_data **presult)
3152 struct cli_pipe_auth_data *result;
3153 NTSTATUS status;
3155 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3156 if (result == NULL) {
3157 return NT_STATUS_NO_MEMORY;
3160 result->auth_type = auth_type;
3161 result->auth_level = auth_level;
3163 result->user_name = talloc_strdup(result, username);
3164 result->domain = talloc_strdup(result, domain);
3165 if ((result->user_name == NULL) || (result->domain == NULL)) {
3166 status = NT_STATUS_NO_MEMORY;
3167 goto fail;
3170 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
3171 if (!NT_STATUS_IS_OK(status)) {
3172 goto fail;
3175 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3177 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3178 if (!NT_STATUS_IS_OK(status)) {
3179 goto fail;
3182 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 goto fail;
3187 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 goto fail;
3193 * Turn off sign+seal to allow selected auth level to turn it back on.
3195 result->a_u.ntlmssp_state->neg_flags &=
3196 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3198 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3199 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3200 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3201 result->a_u.ntlmssp_state->neg_flags
3202 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3205 *presult = result;
3206 return NT_STATUS_OK;
3208 fail:
3209 TALLOC_FREE(result);
3210 return status;
3213 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3214 enum dcerpc_AuthLevel auth_level,
3215 struct netlogon_creds_CredentialState *creds,
3216 struct cli_pipe_auth_data **presult)
3218 struct cli_pipe_auth_data *result;
3220 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3221 if (result == NULL) {
3222 return NT_STATUS_NO_MEMORY;
3225 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3226 result->auth_level = auth_level;
3228 result->user_name = talloc_strdup(result, "");
3229 result->domain = talloc_strdup(result, domain);
3230 if ((result->user_name == NULL) || (result->domain == NULL)) {
3231 goto fail;
3234 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3235 if (result->a_u.schannel_auth == NULL) {
3236 goto fail;
3239 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3240 result->a_u.schannel_auth->seq_num = 0;
3241 result->a_u.schannel_auth->initiator = true;
3242 result->a_u.schannel_auth->creds = creds;
3244 *presult = result;
3245 return NT_STATUS_OK;
3247 fail:
3248 TALLOC_FREE(result);
3249 return NT_STATUS_NO_MEMORY;
3252 #ifdef HAVE_KRB5
3253 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3255 data_blob_free(&auth->session_key);
3256 return 0;
3258 #endif
3260 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3261 enum dcerpc_AuthLevel auth_level,
3262 const char *service_princ,
3263 const char *username,
3264 const char *password,
3265 struct cli_pipe_auth_data **presult)
3267 #ifdef HAVE_KRB5
3268 struct cli_pipe_auth_data *result;
3270 if ((username != NULL) && (password != NULL)) {
3271 int ret = kerberos_kinit_password(username, password, 0, NULL);
3272 if (ret != 0) {
3273 return NT_STATUS_ACCESS_DENIED;
3277 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3278 if (result == NULL) {
3279 return NT_STATUS_NO_MEMORY;
3282 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3283 result->auth_level = auth_level;
3286 * Username / domain need fixing!
3288 result->user_name = talloc_strdup(result, "");
3289 result->domain = talloc_strdup(result, "");
3290 if ((result->user_name == NULL) || (result->domain == NULL)) {
3291 goto fail;
3294 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3295 result, struct kerberos_auth_struct);
3296 if (result->a_u.kerberos_auth == NULL) {
3297 goto fail;
3299 talloc_set_destructor(result->a_u.kerberos_auth,
3300 cli_auth_kerberos_data_destructor);
3302 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3303 result, service_princ);
3304 if (result->a_u.kerberos_auth->service_principal == NULL) {
3305 goto fail;
3308 *presult = result;
3309 return NT_STATUS_OK;
3311 fail:
3312 TALLOC_FREE(result);
3313 return NT_STATUS_NO_MEMORY;
3314 #else
3315 return NT_STATUS_NOT_SUPPORTED;
3316 #endif
3320 * Create an rpc pipe client struct, connecting to a tcp port.
3322 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3323 uint16_t port,
3324 const struct ndr_syntax_id *abstract_syntax,
3325 struct rpc_pipe_client **presult)
3327 struct rpc_pipe_client *result;
3328 struct sockaddr_storage addr;
3329 NTSTATUS status;
3330 int fd;
3332 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3333 if (result == NULL) {
3334 return NT_STATUS_NO_MEMORY;
3337 result->abstract_syntax = *abstract_syntax;
3338 result->transfer_syntax = ndr_transfer_syntax;
3339 result->dispatch = cli_do_rpc_ndr;
3340 result->dispatch_send = cli_do_rpc_ndr_send;
3341 result->dispatch_recv = cli_do_rpc_ndr_recv;
3343 result->desthost = talloc_strdup(result, host);
3344 result->srv_name_slash = talloc_asprintf_strupper_m(
3345 result, "\\\\%s", result->desthost);
3346 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3347 status = NT_STATUS_NO_MEMORY;
3348 goto fail;
3351 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3352 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3354 if (!resolve_name(host, &addr, 0, false)) {
3355 status = NT_STATUS_NOT_FOUND;
3356 goto fail;
3359 status = open_socket_out(&addr, port, 60, &fd);
3360 if (!NT_STATUS_IS_OK(status)) {
3361 goto fail;
3363 set_socket_options(fd, lp_socket_options());
3365 status = rpc_transport_sock_init(result, fd, &result->transport);
3366 if (!NT_STATUS_IS_OK(status)) {
3367 close(fd);
3368 goto fail;
3371 result->transport->transport = NCACN_IP_TCP;
3373 *presult = result;
3374 return NT_STATUS_OK;
3376 fail:
3377 TALLOC_FREE(result);
3378 return status;
3382 * Determine the tcp port on which a dcerpc interface is listening
3383 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3384 * target host.
3386 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3387 const struct ndr_syntax_id *abstract_syntax,
3388 uint16_t *pport)
3390 NTSTATUS status;
3391 struct rpc_pipe_client *epm_pipe = NULL;
3392 struct cli_pipe_auth_data *auth = NULL;
3393 struct dcerpc_binding *map_binding = NULL;
3394 struct dcerpc_binding *res_binding = NULL;
3395 struct epm_twr_t *map_tower = NULL;
3396 struct epm_twr_t *res_towers = NULL;
3397 struct policy_handle *entry_handle = NULL;
3398 uint32_t num_towers = 0;
3399 uint32_t max_towers = 1;
3400 struct epm_twr_p_t towers;
3401 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3403 if (pport == NULL) {
3404 status = NT_STATUS_INVALID_PARAMETER;
3405 goto done;
3408 /* open the connection to the endpoint mapper */
3409 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3410 &ndr_table_epmapper.syntax_id,
3411 &epm_pipe);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 goto done;
3417 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 goto done;
3422 status = rpc_pipe_bind(epm_pipe, auth);
3423 if (!NT_STATUS_IS_OK(status)) {
3424 goto done;
3427 /* create tower for asking the epmapper */
3429 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3430 if (map_binding == NULL) {
3431 status = NT_STATUS_NO_MEMORY;
3432 goto done;
3435 map_binding->transport = NCACN_IP_TCP;
3436 map_binding->object = *abstract_syntax;
3437 map_binding->host = host; /* needed? */
3438 map_binding->endpoint = "0"; /* correct? needed? */
3440 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3441 if (map_tower == NULL) {
3442 status = NT_STATUS_NO_MEMORY;
3443 goto done;
3446 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3447 &(map_tower->tower));
3448 if (!NT_STATUS_IS_OK(status)) {
3449 goto done;
3452 /* allocate further parameters for the epm_Map call */
3454 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3455 if (res_towers == NULL) {
3456 status = NT_STATUS_NO_MEMORY;
3457 goto done;
3459 towers.twr = res_towers;
3461 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3462 if (entry_handle == NULL) {
3463 status = NT_STATUS_NO_MEMORY;
3464 goto done;
3467 /* ask the endpoint mapper for the port */
3469 status = rpccli_epm_Map(epm_pipe,
3470 tmp_ctx,
3471 CONST_DISCARD(struct GUID *,
3472 &(abstract_syntax->uuid)),
3473 map_tower,
3474 entry_handle,
3475 max_towers,
3476 &num_towers,
3477 &towers);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 goto done;
3483 if (num_towers != 1) {
3484 status = NT_STATUS_UNSUCCESSFUL;
3485 goto done;
3488 /* extract the port from the answer */
3490 status = dcerpc_binding_from_tower(tmp_ctx,
3491 &(towers.twr->tower),
3492 &res_binding);
3493 if (!NT_STATUS_IS_OK(status)) {
3494 goto done;
3497 /* are further checks here necessary? */
3498 if (res_binding->transport != NCACN_IP_TCP) {
3499 status = NT_STATUS_UNSUCCESSFUL;
3500 goto done;
3503 *pport = (uint16_t)atoi(res_binding->endpoint);
3505 done:
3506 TALLOC_FREE(tmp_ctx);
3507 return status;
3511 * Create a rpc pipe client struct, connecting to a host via tcp.
3512 * The port is determined by asking the endpoint mapper on the given
3513 * host.
3515 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3516 const struct ndr_syntax_id *abstract_syntax,
3517 struct rpc_pipe_client **presult)
3519 NTSTATUS status;
3520 uint16_t port = 0;
3522 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 return status;
3527 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3528 abstract_syntax, presult);
3531 /********************************************************************
3532 Create a rpc pipe client struct, connecting to a unix domain socket
3533 ********************************************************************/
3534 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3535 const struct ndr_syntax_id *abstract_syntax,
3536 struct rpc_pipe_client **presult)
3538 struct rpc_pipe_client *result;
3539 struct sockaddr_un addr;
3540 NTSTATUS status;
3541 int fd;
3543 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3544 if (result == NULL) {
3545 return NT_STATUS_NO_MEMORY;
3548 result->abstract_syntax = *abstract_syntax;
3549 result->transfer_syntax = ndr_transfer_syntax;
3550 result->dispatch = cli_do_rpc_ndr;
3551 result->dispatch_send = cli_do_rpc_ndr_send;
3552 result->dispatch_recv = cli_do_rpc_ndr_recv;
3554 result->desthost = get_myname(result);
3555 result->srv_name_slash = talloc_asprintf_strupper_m(
3556 result, "\\\\%s", result->desthost);
3557 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3558 status = NT_STATUS_NO_MEMORY;
3559 goto fail;
3562 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3563 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3565 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3566 if (fd == -1) {
3567 status = map_nt_error_from_unix(errno);
3568 goto fail;
3571 ZERO_STRUCT(addr);
3572 addr.sun_family = AF_UNIX;
3573 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3575 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3576 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3577 strerror(errno)));
3578 close(fd);
3579 return map_nt_error_from_unix(errno);
3582 status = rpc_transport_sock_init(result, fd, &result->transport);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 close(fd);
3585 goto fail;
3588 result->transport->transport = NCALRPC;
3590 *presult = result;
3591 return NT_STATUS_OK;
3593 fail:
3594 TALLOC_FREE(result);
3595 return status;
3598 static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p)
3600 struct cli_state *cli;
3602 cli = rpc_pipe_np_smb_conn(p);
3603 if (cli != NULL) {
3604 DLIST_REMOVE(cli->pipe_list, p);
3606 return 0;
3609 /****************************************************************************
3610 Open a named pipe over SMB to a remote server.
3612 * CAVEAT CALLER OF THIS FUNCTION:
3613 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3614 * so be sure that this function is called AFTER any structure (vs pointer)
3615 * assignment of the cli. In particular, libsmbclient does structure
3616 * assignments of cli, which invalidates the data in the returned
3617 * rpc_pipe_client if this function is called before the structure assignment
3618 * of cli.
3620 ****************************************************************************/
3622 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3623 const struct ndr_syntax_id *abstract_syntax,
3624 struct rpc_pipe_client **presult)
3626 struct rpc_pipe_client *result;
3627 NTSTATUS status;
3629 /* sanity check to protect against crashes */
3631 if ( !cli ) {
3632 return NT_STATUS_INVALID_HANDLE;
3635 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3636 if (result == NULL) {
3637 return NT_STATUS_NO_MEMORY;
3640 result->abstract_syntax = *abstract_syntax;
3641 result->transfer_syntax = ndr_transfer_syntax;
3642 result->dispatch = cli_do_rpc_ndr;
3643 result->dispatch_send = cli_do_rpc_ndr_send;
3644 result->dispatch_recv = cli_do_rpc_ndr_recv;
3645 result->desthost = talloc_strdup(result, cli->desthost);
3646 result->srv_name_slash = talloc_asprintf_strupper_m(
3647 result, "\\\\%s", result->desthost);
3649 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3650 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3652 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3653 TALLOC_FREE(result);
3654 return NT_STATUS_NO_MEMORY;
3657 status = rpc_transport_np_init(result, cli, abstract_syntax,
3658 &result->transport);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 TALLOC_FREE(result);
3661 return status;
3664 result->transport->transport = NCACN_NP;
3666 DLIST_ADD(cli->pipe_list, result);
3667 talloc_set_destructor(result, rpc_pipe_client_np_destructor);
3669 *presult = result;
3670 return NT_STATUS_OK;
3673 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3674 struct rpc_cli_smbd_conn *conn,
3675 const struct ndr_syntax_id *syntax,
3676 struct rpc_pipe_client **presult)
3678 struct rpc_pipe_client *result;
3679 struct cli_pipe_auth_data *auth;
3680 NTSTATUS status;
3682 result = talloc(mem_ctx, struct rpc_pipe_client);
3683 if (result == NULL) {
3684 return NT_STATUS_NO_MEMORY;
3686 result->abstract_syntax = *syntax;
3687 result->transfer_syntax = ndr_transfer_syntax;
3688 result->dispatch = cli_do_rpc_ndr;
3689 result->dispatch_send = cli_do_rpc_ndr_send;
3690 result->dispatch_recv = cli_do_rpc_ndr_recv;
3691 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3692 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3694 result->desthost = talloc_strdup(result, global_myname());
3695 result->srv_name_slash = talloc_asprintf_strupper_m(
3696 result, "\\\\%s", global_myname());
3697 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3698 TALLOC_FREE(result);
3699 return NT_STATUS_NO_MEMORY;
3702 status = rpc_transport_smbd_init(result, conn, syntax,
3703 &result->transport);
3704 if (!NT_STATUS_IS_OK(status)) {
3705 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3706 nt_errstr(status)));
3707 TALLOC_FREE(result);
3708 return status;
3711 status = rpccli_anon_bind_data(result, &auth);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3714 nt_errstr(status)));
3715 TALLOC_FREE(result);
3716 return status;
3719 status = rpc_pipe_bind(result, auth);
3720 if (!NT_STATUS_IS_OK(status)) {
3721 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3722 TALLOC_FREE(result);
3723 return status;
3726 result->transport->transport = NCACN_INTERNAL;
3728 *presult = result;
3729 return NT_STATUS_OK;
3732 /****************************************************************************
3733 Open a pipe to a remote server.
3734 ****************************************************************************/
3736 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3737 enum dcerpc_transport_t transport,
3738 const struct ndr_syntax_id *interface,
3739 struct rpc_pipe_client **presult)
3741 switch (transport) {
3742 case NCACN_IP_TCP:
3743 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3744 presult);
3745 case NCACN_NP:
3746 return rpc_pipe_open_np(cli, interface, presult);
3747 default:
3748 return NT_STATUS_NOT_IMPLEMENTED;
3752 /****************************************************************************
3753 Open a named pipe to an SMB server and bind anonymously.
3754 ****************************************************************************/
3756 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3757 enum dcerpc_transport_t transport,
3758 const struct ndr_syntax_id *interface,
3759 struct rpc_pipe_client **presult)
3761 struct rpc_pipe_client *result;
3762 struct cli_pipe_auth_data *auth;
3763 NTSTATUS status;
3765 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 return status;
3770 status = rpccli_anon_bind_data(result, &auth);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3773 nt_errstr(status)));
3774 TALLOC_FREE(result);
3775 return status;
3779 * This is a bit of an abstraction violation due to the fact that an
3780 * anonymous bind on an authenticated SMB inherits the user/domain
3781 * from the enclosing SMB creds
3784 TALLOC_FREE(auth->user_name);
3785 TALLOC_FREE(auth->domain);
3787 auth->user_name = talloc_strdup(auth, cli->user_name);
3788 auth->domain = talloc_strdup(auth, cli->domain);
3789 auth->user_session_key = data_blob_talloc(auth,
3790 cli->user_session_key.data,
3791 cli->user_session_key.length);
3793 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3794 TALLOC_FREE(result);
3795 return NT_STATUS_NO_MEMORY;
3798 status = rpc_pipe_bind(result, auth);
3799 if (!NT_STATUS_IS_OK(status)) {
3800 int lvl = 0;
3801 if (ndr_syntax_id_equal(interface,
3802 &ndr_table_dssetup.syntax_id)) {
3803 /* non AD domains just don't have this pipe, avoid
3804 * level 0 statement in that case - gd */
3805 lvl = 3;
3807 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3808 "%s failed with error %s\n",
3809 get_pipe_name_from_syntax(talloc_tos(), interface),
3810 nt_errstr(status) ));
3811 TALLOC_FREE(result);
3812 return status;
3815 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3816 "%s and bound anonymously.\n",
3817 get_pipe_name_from_syntax(talloc_tos(), interface),
3818 cli->desthost));
3820 *presult = result;
3821 return NT_STATUS_OK;
3824 /****************************************************************************
3825 ****************************************************************************/
3827 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3828 const struct ndr_syntax_id *interface,
3829 struct rpc_pipe_client **presult)
3831 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3832 interface, presult);
3835 /****************************************************************************
3836 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3837 ****************************************************************************/
3839 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3840 const struct ndr_syntax_id *interface,
3841 enum dcerpc_transport_t transport,
3842 enum pipe_auth_type auth_type,
3843 enum dcerpc_AuthLevel auth_level,
3844 const char *domain,
3845 const char *username,
3846 const char *password,
3847 struct rpc_pipe_client **presult)
3849 struct rpc_pipe_client *result;
3850 struct cli_pipe_auth_data *auth;
3851 NTSTATUS status;
3853 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 return status;
3858 status = rpccli_ntlmssp_bind_data(
3859 result, auth_type, auth_level, domain, username,
3860 password, &auth);
3861 if (!NT_STATUS_IS_OK(status)) {
3862 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3863 nt_errstr(status)));
3864 goto err;
3867 status = rpc_pipe_bind(result, auth);
3868 if (!NT_STATUS_IS_OK(status)) {
3869 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3870 nt_errstr(status) ));
3871 goto err;
3874 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3875 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3876 get_pipe_name_from_syntax(talloc_tos(), interface),
3877 cli->desthost, domain, username ));
3879 *presult = result;
3880 return NT_STATUS_OK;
3882 err:
3884 TALLOC_FREE(result);
3885 return status;
3888 /****************************************************************************
3889 External interface.
3890 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3891 ****************************************************************************/
3893 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3894 const struct ndr_syntax_id *interface,
3895 enum dcerpc_transport_t transport,
3896 enum dcerpc_AuthLevel auth_level,
3897 const char *domain,
3898 const char *username,
3899 const char *password,
3900 struct rpc_pipe_client **presult)
3902 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3903 interface,
3904 transport,
3905 PIPE_AUTH_TYPE_NTLMSSP,
3906 auth_level,
3907 domain,
3908 username,
3909 password,
3910 presult);
3913 /****************************************************************************
3914 External interface.
3915 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3916 ****************************************************************************/
3918 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3919 const struct ndr_syntax_id *interface,
3920 enum dcerpc_transport_t transport,
3921 enum dcerpc_AuthLevel auth_level,
3922 const char *domain,
3923 const char *username,
3924 const char *password,
3925 struct rpc_pipe_client **presult)
3927 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3928 interface,
3929 transport,
3930 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3931 auth_level,
3932 domain,
3933 username,
3934 password,
3935 presult);
3938 /****************************************************************************
3939 Get a the schannel session key out of an already opened netlogon pipe.
3940 ****************************************************************************/
3941 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3942 struct cli_state *cli,
3943 const char *domain,
3944 uint32 *pneg_flags)
3946 enum netr_SchannelType sec_chan_type = 0;
3947 unsigned char machine_pwd[16];
3948 const char *machine_account;
3949 NTSTATUS status;
3951 /* Get the machine account credentials from secrets.tdb. */
3952 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3953 &sec_chan_type))
3955 DEBUG(0, ("get_schannel_session_key: could not fetch "
3956 "trust account password for domain '%s'\n",
3957 domain));
3958 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3961 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3962 cli->desthost, /* server name */
3963 domain, /* domain */
3964 global_myname(), /* client name */
3965 machine_account, /* machine account name */
3966 machine_pwd,
3967 sec_chan_type,
3968 pneg_flags);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 DEBUG(3, ("get_schannel_session_key_common: "
3972 "rpccli_netlogon_setup_creds failed with result %s "
3973 "to server %s, domain %s, machine account %s.\n",
3974 nt_errstr(status), cli->desthost, domain,
3975 machine_account ));
3976 return status;
3979 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3980 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3981 cli->desthost));
3982 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3985 return NT_STATUS_OK;;
3988 /****************************************************************************
3989 Open a netlogon pipe and get the schannel session key.
3990 Now exposed to external callers.
3991 ****************************************************************************/
3994 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3995 const char *domain,
3996 uint32 *pneg_flags,
3997 struct rpc_pipe_client **presult)
3999 struct rpc_pipe_client *netlogon_pipe = NULL;
4000 NTSTATUS status;
4002 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
4003 &netlogon_pipe);
4004 if (!NT_STATUS_IS_OK(status)) {
4005 return status;
4008 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4009 pneg_flags);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 TALLOC_FREE(netlogon_pipe);
4012 return status;
4015 *presult = netlogon_pipe;
4016 return NT_STATUS_OK;
4019 /****************************************************************************
4020 External interface.
4021 Open a named pipe to an SMB server and bind using schannel (bind type 68)
4022 using session_key. sign and seal.
4024 The *pdc will be stolen onto this new pipe
4025 ****************************************************************************/
4027 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
4028 const struct ndr_syntax_id *interface,
4029 enum dcerpc_transport_t transport,
4030 enum dcerpc_AuthLevel auth_level,
4031 const char *domain,
4032 struct netlogon_creds_CredentialState **pdc,
4033 struct rpc_pipe_client **presult)
4035 struct rpc_pipe_client *result;
4036 struct cli_pipe_auth_data *auth;
4037 NTSTATUS status;
4039 status = cli_rpc_pipe_open(cli, transport, interface, &result);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 return status;
4044 status = rpccli_schannel_bind_data(result, domain, auth_level,
4045 *pdc, &auth);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4048 nt_errstr(status)));
4049 TALLOC_FREE(result);
4050 return status;
4053 status = rpc_pipe_bind(result, auth);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4056 "cli_rpc_pipe_bind failed with error %s\n",
4057 nt_errstr(status) ));
4058 TALLOC_FREE(result);
4059 return status;
4063 * The credentials on a new netlogon pipe are the ones we are passed
4064 * in - reference them in
4066 result->dc = talloc_move(result, pdc);
4068 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4069 "for domain %s and bound using schannel.\n",
4070 get_pipe_name_from_syntax(talloc_tos(), interface),
4071 cli->desthost, domain ));
4073 *presult = result;
4074 return NT_STATUS_OK;
4077 /****************************************************************************
4078 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4079 Fetch the session key ourselves using a temporary netlogon pipe. This
4080 version uses an ntlmssp auth bound netlogon pipe to get the key.
4081 ****************************************************************************/
4083 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4084 const char *domain,
4085 const char *username,
4086 const char *password,
4087 uint32 *pneg_flags,
4088 struct rpc_pipe_client **presult)
4090 struct rpc_pipe_client *netlogon_pipe = NULL;
4091 NTSTATUS status;
4093 status = cli_rpc_pipe_open_spnego_ntlmssp(
4094 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4095 DCERPC_AUTH_LEVEL_PRIVACY,
4096 domain, username, password, &netlogon_pipe);
4097 if (!NT_STATUS_IS_OK(status)) {
4098 return status;
4101 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4102 pneg_flags);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 TALLOC_FREE(netlogon_pipe);
4105 return status;
4108 *presult = netlogon_pipe;
4109 return NT_STATUS_OK;
4112 /****************************************************************************
4113 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4114 Fetch the session key ourselves using a temporary netlogon pipe. This version
4115 uses an ntlmssp bind to get the session key.
4116 ****************************************************************************/
4118 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4119 const struct ndr_syntax_id *interface,
4120 enum dcerpc_transport_t transport,
4121 enum dcerpc_AuthLevel auth_level,
4122 const char *domain,
4123 const char *username,
4124 const char *password,
4125 struct rpc_pipe_client **presult)
4127 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4128 struct rpc_pipe_client *netlogon_pipe = NULL;
4129 struct rpc_pipe_client *result = NULL;
4130 NTSTATUS status;
4132 status = get_schannel_session_key_auth_ntlmssp(
4133 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4134 if (!NT_STATUS_IS_OK(status)) {
4135 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4136 "key from server %s for domain %s.\n",
4137 cli->desthost, domain ));
4138 return status;
4141 status = cli_rpc_pipe_open_schannel_with_key(
4142 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4143 &result);
4145 /* Now we've bound using the session key we can close the netlog pipe. */
4146 TALLOC_FREE(netlogon_pipe);
4148 if (NT_STATUS_IS_OK(status)) {
4149 *presult = result;
4151 return status;
4154 /****************************************************************************
4155 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4156 Fetch the session key ourselves using a temporary netlogon pipe.
4157 ****************************************************************************/
4159 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4160 const struct ndr_syntax_id *interface,
4161 enum dcerpc_transport_t transport,
4162 enum dcerpc_AuthLevel auth_level,
4163 const char *domain,
4164 struct rpc_pipe_client **presult)
4166 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4167 struct rpc_pipe_client *netlogon_pipe = NULL;
4168 struct rpc_pipe_client *result = NULL;
4169 NTSTATUS status;
4171 status = get_schannel_session_key(cli, domain, &neg_flags,
4172 &netlogon_pipe);
4173 if (!NT_STATUS_IS_OK(status)) {
4174 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4175 "key from server %s for domain %s.\n",
4176 cli->desthost, domain ));
4177 return status;
4180 status = cli_rpc_pipe_open_schannel_with_key(
4181 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4182 &result);
4184 /* Now we've bound using the session key we can close the netlog pipe. */
4185 TALLOC_FREE(netlogon_pipe);
4187 if (NT_STATUS_IS_OK(status)) {
4188 *presult = result;
4191 return status;
4194 /****************************************************************************
4195 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4196 The idea is this can be called with service_princ, username and password all
4197 NULL so long as the caller has a TGT.
4198 ****************************************************************************/
4200 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4201 const struct ndr_syntax_id *interface,
4202 enum dcerpc_AuthLevel auth_level,
4203 const char *service_princ,
4204 const char *username,
4205 const char *password,
4206 struct rpc_pipe_client **presult)
4208 #ifdef HAVE_KRB5
4209 struct rpc_pipe_client *result;
4210 struct cli_pipe_auth_data *auth;
4211 NTSTATUS status;
4213 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4214 if (!NT_STATUS_IS_OK(status)) {
4215 return status;
4218 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4219 username, password, &auth);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4222 nt_errstr(status)));
4223 TALLOC_FREE(result);
4224 return status;
4227 status = rpc_pipe_bind(result, auth);
4228 if (!NT_STATUS_IS_OK(status)) {
4229 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4230 "with error %s\n", nt_errstr(status)));
4231 TALLOC_FREE(result);
4232 return status;
4235 *presult = result;
4236 return NT_STATUS_OK;
4237 #else
4238 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4239 return NT_STATUS_NOT_IMPLEMENTED;
4240 #endif
4243 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4244 struct rpc_pipe_client *cli,
4245 DATA_BLOB *session_key)
4247 if (!session_key || !cli) {
4248 return NT_STATUS_INVALID_PARAMETER;
4251 if (!cli->auth) {
4252 return NT_STATUS_INVALID_PARAMETER;
4255 switch (cli->auth->auth_type) {
4256 case PIPE_AUTH_TYPE_SCHANNEL:
4257 *session_key = data_blob_talloc(mem_ctx,
4258 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4259 break;
4260 case PIPE_AUTH_TYPE_NTLMSSP:
4261 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4262 *session_key = data_blob_talloc(mem_ctx,
4263 cli->auth->a_u.ntlmssp_state->session_key.data,
4264 cli->auth->a_u.ntlmssp_state->session_key.length);
4265 break;
4266 case PIPE_AUTH_TYPE_KRB5:
4267 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4268 *session_key = data_blob_talloc(mem_ctx,
4269 cli->auth->a_u.kerberos_auth->session_key.data,
4270 cli->auth->a_u.kerberos_auth->session_key.length);
4271 break;
4272 case PIPE_AUTH_TYPE_NONE:
4273 *session_key = data_blob_talloc(mem_ctx,
4274 cli->auth->user_session_key.data,
4275 cli->auth->user_session_key.length);
4276 break;
4277 default:
4278 return NT_STATUS_NO_USER_SESSION_KEY;
4281 return NT_STATUS_OK;