s4:librpc/rpc: make PyErr_SetDCERPCStatus() static
[Samba/gebeck_regimport.git] / source3 / rpc_client / cli_pipe.c
blob8d33d7713f40afc0c9028bde396f22ce54386a1e
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 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
3069 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3070 unsigned int timeout)
3072 unsigned int old;
3074 if (rpc_cli->transport == NULL) {
3075 return RPCCLI_DEFAULT_TIMEOUT;
3078 if (rpc_cli->transport->set_timeout == NULL) {
3079 return RPCCLI_DEFAULT_TIMEOUT;
3082 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
3083 if (old == 0) {
3084 return RPCCLI_DEFAULT_TIMEOUT;
3087 return old;
3090 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
3092 if (rpc_cli == NULL) {
3093 return false;
3096 if (rpc_cli->transport == NULL) {
3097 return false;
3100 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
3103 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3105 struct cli_state *cli;
3107 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3108 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3109 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3110 return true;
3113 cli = rpc_pipe_np_smb_conn(rpc_cli);
3114 if (cli == NULL) {
3115 return false;
3117 E_md4hash(cli->password ? cli->password : "", nt_hash);
3118 return true;
3121 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3122 struct cli_pipe_auth_data **presult)
3124 struct cli_pipe_auth_data *result;
3126 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3127 if (result == NULL) {
3128 return NT_STATUS_NO_MEMORY;
3131 result->auth_type = PIPE_AUTH_TYPE_NONE;
3132 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3134 result->user_name = talloc_strdup(result, "");
3135 result->domain = talloc_strdup(result, "");
3136 if ((result->user_name == NULL) || (result->domain == NULL)) {
3137 TALLOC_FREE(result);
3138 return NT_STATUS_NO_MEMORY;
3141 *presult = result;
3142 return NT_STATUS_OK;
3145 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3147 ntlmssp_end(&auth->a_u.ntlmssp_state);
3148 return 0;
3151 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3152 enum pipe_auth_type auth_type,
3153 enum dcerpc_AuthLevel auth_level,
3154 const char *domain,
3155 const char *username,
3156 const char *password,
3157 struct cli_pipe_auth_data **presult)
3159 struct cli_pipe_auth_data *result;
3160 NTSTATUS status;
3162 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3163 if (result == NULL) {
3164 return NT_STATUS_NO_MEMORY;
3167 result->auth_type = auth_type;
3168 result->auth_level = auth_level;
3170 result->user_name = talloc_strdup(result, username);
3171 result->domain = talloc_strdup(result, domain);
3172 if ((result->user_name == NULL) || (result->domain == NULL)) {
3173 status = NT_STATUS_NO_MEMORY;
3174 goto fail;
3177 status = ntlmssp_client_start(NULL,
3178 global_myname(),
3179 lp_workgroup(),
3180 lp_client_ntlmv2_auth(),
3181 &result->a_u.ntlmssp_state);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 goto fail;
3186 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3188 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3189 if (!NT_STATUS_IS_OK(status)) {
3190 goto fail;
3193 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 goto fail;
3198 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3199 if (!NT_STATUS_IS_OK(status)) {
3200 goto fail;
3204 * Turn off sign+seal to allow selected auth level to turn it back on.
3206 result->a_u.ntlmssp_state->neg_flags &=
3207 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3209 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3210 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3211 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3212 result->a_u.ntlmssp_state->neg_flags
3213 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3216 *presult = result;
3217 return NT_STATUS_OK;
3219 fail:
3220 TALLOC_FREE(result);
3221 return status;
3224 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3225 enum dcerpc_AuthLevel auth_level,
3226 struct netlogon_creds_CredentialState *creds,
3227 struct cli_pipe_auth_data **presult)
3229 struct cli_pipe_auth_data *result;
3231 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3232 if (result == NULL) {
3233 return NT_STATUS_NO_MEMORY;
3236 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3237 result->auth_level = auth_level;
3239 result->user_name = talloc_strdup(result, "");
3240 result->domain = talloc_strdup(result, domain);
3241 if ((result->user_name == NULL) || (result->domain == NULL)) {
3242 goto fail;
3245 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3246 if (result->a_u.schannel_auth == NULL) {
3247 goto fail;
3250 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3251 result->a_u.schannel_auth->seq_num = 0;
3252 result->a_u.schannel_auth->initiator = true;
3253 result->a_u.schannel_auth->creds = creds;
3255 *presult = result;
3256 return NT_STATUS_OK;
3258 fail:
3259 TALLOC_FREE(result);
3260 return NT_STATUS_NO_MEMORY;
3263 #ifdef HAVE_KRB5
3264 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3266 data_blob_free(&auth->session_key);
3267 return 0;
3269 #endif
3271 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3272 enum dcerpc_AuthLevel auth_level,
3273 const char *service_princ,
3274 const char *username,
3275 const char *password,
3276 struct cli_pipe_auth_data **presult)
3278 #ifdef HAVE_KRB5
3279 struct cli_pipe_auth_data *result;
3281 if ((username != NULL) && (password != NULL)) {
3282 int ret = kerberos_kinit_password(username, password, 0, NULL);
3283 if (ret != 0) {
3284 return NT_STATUS_ACCESS_DENIED;
3288 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3289 if (result == NULL) {
3290 return NT_STATUS_NO_MEMORY;
3293 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3294 result->auth_level = auth_level;
3297 * Username / domain need fixing!
3299 result->user_name = talloc_strdup(result, "");
3300 result->domain = talloc_strdup(result, "");
3301 if ((result->user_name == NULL) || (result->domain == NULL)) {
3302 goto fail;
3305 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3306 result, struct kerberos_auth_struct);
3307 if (result->a_u.kerberos_auth == NULL) {
3308 goto fail;
3310 talloc_set_destructor(result->a_u.kerberos_auth,
3311 cli_auth_kerberos_data_destructor);
3313 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3314 result, service_princ);
3315 if (result->a_u.kerberos_auth->service_principal == NULL) {
3316 goto fail;
3319 *presult = result;
3320 return NT_STATUS_OK;
3322 fail:
3323 TALLOC_FREE(result);
3324 return NT_STATUS_NO_MEMORY;
3325 #else
3326 return NT_STATUS_NOT_SUPPORTED;
3327 #endif
3331 * Create an rpc pipe client struct, connecting to a tcp port.
3333 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3334 uint16_t port,
3335 const struct ndr_syntax_id *abstract_syntax,
3336 struct rpc_pipe_client **presult)
3338 struct rpc_pipe_client *result;
3339 struct sockaddr_storage addr;
3340 NTSTATUS status;
3341 int fd;
3343 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3344 if (result == NULL) {
3345 return NT_STATUS_NO_MEMORY;
3348 result->abstract_syntax = *abstract_syntax;
3349 result->transfer_syntax = ndr_transfer_syntax;
3350 result->dispatch = cli_do_rpc_ndr;
3351 result->dispatch_send = cli_do_rpc_ndr_send;
3352 result->dispatch_recv = cli_do_rpc_ndr_recv;
3354 result->desthost = talloc_strdup(result, host);
3355 result->srv_name_slash = talloc_asprintf_strupper_m(
3356 result, "\\\\%s", result->desthost);
3357 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3358 status = NT_STATUS_NO_MEMORY;
3359 goto fail;
3362 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3363 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3365 if (!resolve_name(host, &addr, 0, false)) {
3366 status = NT_STATUS_NOT_FOUND;
3367 goto fail;
3370 status = open_socket_out(&addr, port, 60, &fd);
3371 if (!NT_STATUS_IS_OK(status)) {
3372 goto fail;
3374 set_socket_options(fd, lp_socket_options());
3376 status = rpc_transport_sock_init(result, fd, &result->transport);
3377 if (!NT_STATUS_IS_OK(status)) {
3378 close(fd);
3379 goto fail;
3382 result->transport->transport = NCACN_IP_TCP;
3384 *presult = result;
3385 return NT_STATUS_OK;
3387 fail:
3388 TALLOC_FREE(result);
3389 return status;
3393 * Determine the tcp port on which a dcerpc interface is listening
3394 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3395 * target host.
3397 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3398 const struct ndr_syntax_id *abstract_syntax,
3399 uint16_t *pport)
3401 NTSTATUS status;
3402 struct rpc_pipe_client *epm_pipe = NULL;
3403 struct cli_pipe_auth_data *auth = NULL;
3404 struct dcerpc_binding *map_binding = NULL;
3405 struct dcerpc_binding *res_binding = NULL;
3406 struct epm_twr_t *map_tower = NULL;
3407 struct epm_twr_t *res_towers = NULL;
3408 struct policy_handle *entry_handle = NULL;
3409 uint32_t num_towers = 0;
3410 uint32_t max_towers = 1;
3411 struct epm_twr_p_t towers;
3412 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3414 if (pport == NULL) {
3415 status = NT_STATUS_INVALID_PARAMETER;
3416 goto done;
3419 /* open the connection to the endpoint mapper */
3420 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3421 &ndr_table_epmapper.syntax_id,
3422 &epm_pipe);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 goto done;
3428 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3429 if (!NT_STATUS_IS_OK(status)) {
3430 goto done;
3433 status = rpc_pipe_bind(epm_pipe, auth);
3434 if (!NT_STATUS_IS_OK(status)) {
3435 goto done;
3438 /* create tower for asking the epmapper */
3440 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3441 if (map_binding == NULL) {
3442 status = NT_STATUS_NO_MEMORY;
3443 goto done;
3446 map_binding->transport = NCACN_IP_TCP;
3447 map_binding->object = *abstract_syntax;
3448 map_binding->host = host; /* needed? */
3449 map_binding->endpoint = "0"; /* correct? needed? */
3451 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3452 if (map_tower == NULL) {
3453 status = NT_STATUS_NO_MEMORY;
3454 goto done;
3457 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3458 &(map_tower->tower));
3459 if (!NT_STATUS_IS_OK(status)) {
3460 goto done;
3463 /* allocate further parameters for the epm_Map call */
3465 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3466 if (res_towers == NULL) {
3467 status = NT_STATUS_NO_MEMORY;
3468 goto done;
3470 towers.twr = res_towers;
3472 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3473 if (entry_handle == NULL) {
3474 status = NT_STATUS_NO_MEMORY;
3475 goto done;
3478 /* ask the endpoint mapper for the port */
3480 status = rpccli_epm_Map(epm_pipe,
3481 tmp_ctx,
3482 CONST_DISCARD(struct GUID *,
3483 &(abstract_syntax->uuid)),
3484 map_tower,
3485 entry_handle,
3486 max_towers,
3487 &num_towers,
3488 &towers);
3490 if (!NT_STATUS_IS_OK(status)) {
3491 goto done;
3494 if (num_towers != 1) {
3495 status = NT_STATUS_UNSUCCESSFUL;
3496 goto done;
3499 /* extract the port from the answer */
3501 status = dcerpc_binding_from_tower(tmp_ctx,
3502 &(towers.twr->tower),
3503 &res_binding);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 goto done;
3508 /* are further checks here necessary? */
3509 if (res_binding->transport != NCACN_IP_TCP) {
3510 status = NT_STATUS_UNSUCCESSFUL;
3511 goto done;
3514 *pport = (uint16_t)atoi(res_binding->endpoint);
3516 done:
3517 TALLOC_FREE(tmp_ctx);
3518 return status;
3522 * Create a rpc pipe client struct, connecting to a host via tcp.
3523 * The port is determined by asking the endpoint mapper on the given
3524 * host.
3526 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3527 const struct ndr_syntax_id *abstract_syntax,
3528 struct rpc_pipe_client **presult)
3530 NTSTATUS status;
3531 uint16_t port = 0;
3533 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3534 if (!NT_STATUS_IS_OK(status)) {
3535 return status;
3538 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3539 abstract_syntax, presult);
3542 /********************************************************************
3543 Create a rpc pipe client struct, connecting to a unix domain socket
3544 ********************************************************************/
3545 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3546 const struct ndr_syntax_id *abstract_syntax,
3547 struct rpc_pipe_client **presult)
3549 struct rpc_pipe_client *result;
3550 struct sockaddr_un addr;
3551 NTSTATUS status;
3552 int fd;
3554 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3555 if (result == NULL) {
3556 return NT_STATUS_NO_MEMORY;
3559 result->abstract_syntax = *abstract_syntax;
3560 result->transfer_syntax = ndr_transfer_syntax;
3561 result->dispatch = cli_do_rpc_ndr;
3562 result->dispatch_send = cli_do_rpc_ndr_send;
3563 result->dispatch_recv = cli_do_rpc_ndr_recv;
3565 result->desthost = get_myname(result);
3566 result->srv_name_slash = talloc_asprintf_strupper_m(
3567 result, "\\\\%s", result->desthost);
3568 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3569 status = NT_STATUS_NO_MEMORY;
3570 goto fail;
3573 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3574 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3576 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3577 if (fd == -1) {
3578 status = map_nt_error_from_unix(errno);
3579 goto fail;
3582 ZERO_STRUCT(addr);
3583 addr.sun_family = AF_UNIX;
3584 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3586 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3587 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3588 strerror(errno)));
3589 close(fd);
3590 return map_nt_error_from_unix(errno);
3593 status = rpc_transport_sock_init(result, fd, &result->transport);
3594 if (!NT_STATUS_IS_OK(status)) {
3595 close(fd);
3596 goto fail;
3599 result->transport->transport = NCALRPC;
3601 *presult = result;
3602 return NT_STATUS_OK;
3604 fail:
3605 TALLOC_FREE(result);
3606 return status;
3609 struct rpc_pipe_client_np_ref {
3610 struct cli_state *cli;
3611 struct rpc_pipe_client *pipe;
3614 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3616 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3617 return 0;
3620 /****************************************************************************
3621 Open a named pipe over SMB to a remote server.
3623 * CAVEAT CALLER OF THIS FUNCTION:
3624 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3625 * so be sure that this function is called AFTER any structure (vs pointer)
3626 * assignment of the cli. In particular, libsmbclient does structure
3627 * assignments of cli, which invalidates the data in the returned
3628 * rpc_pipe_client if this function is called before the structure assignment
3629 * of cli.
3631 ****************************************************************************/
3633 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3634 const struct ndr_syntax_id *abstract_syntax,
3635 struct rpc_pipe_client **presult)
3637 struct rpc_pipe_client *result;
3638 NTSTATUS status;
3639 struct rpc_pipe_client_np_ref *np_ref;
3641 /* sanity check to protect against crashes */
3643 if ( !cli ) {
3644 return NT_STATUS_INVALID_HANDLE;
3647 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3648 if (result == NULL) {
3649 return NT_STATUS_NO_MEMORY;
3652 result->abstract_syntax = *abstract_syntax;
3653 result->transfer_syntax = ndr_transfer_syntax;
3654 result->dispatch = cli_do_rpc_ndr;
3655 result->dispatch_send = cli_do_rpc_ndr_send;
3656 result->dispatch_recv = cli_do_rpc_ndr_recv;
3657 result->desthost = talloc_strdup(result, cli->desthost);
3658 result->srv_name_slash = talloc_asprintf_strupper_m(
3659 result, "\\\\%s", result->desthost);
3661 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3662 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3664 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3665 TALLOC_FREE(result);
3666 return NT_STATUS_NO_MEMORY;
3669 status = rpc_transport_np_init(result, cli, abstract_syntax,
3670 &result->transport);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 TALLOC_FREE(result);
3673 return status;
3676 result->transport->transport = NCACN_NP;
3678 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3679 if (np_ref == NULL) {
3680 TALLOC_FREE(result);
3681 return NT_STATUS_NO_MEMORY;
3683 np_ref->cli = cli;
3684 np_ref->pipe = result;
3686 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3687 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3689 *presult = result;
3690 return NT_STATUS_OK;
3693 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3694 struct rpc_cli_smbd_conn *conn,
3695 const struct ndr_syntax_id *syntax,
3696 struct rpc_pipe_client **presult)
3698 struct rpc_pipe_client *result;
3699 struct cli_pipe_auth_data *auth;
3700 NTSTATUS status;
3702 result = talloc(mem_ctx, struct rpc_pipe_client);
3703 if (result == NULL) {
3704 return NT_STATUS_NO_MEMORY;
3706 result->abstract_syntax = *syntax;
3707 result->transfer_syntax = ndr_transfer_syntax;
3708 result->dispatch = cli_do_rpc_ndr;
3709 result->dispatch_send = cli_do_rpc_ndr_send;
3710 result->dispatch_recv = cli_do_rpc_ndr_recv;
3711 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3712 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3714 result->desthost = talloc_strdup(result, global_myname());
3715 result->srv_name_slash = talloc_asprintf_strupper_m(
3716 result, "\\\\%s", global_myname());
3717 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3718 TALLOC_FREE(result);
3719 return NT_STATUS_NO_MEMORY;
3722 status = rpc_transport_smbd_init(result, conn, syntax,
3723 &result->transport);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3726 nt_errstr(status)));
3727 TALLOC_FREE(result);
3728 return status;
3731 status = rpccli_anon_bind_data(result, &auth);
3732 if (!NT_STATUS_IS_OK(status)) {
3733 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3734 nt_errstr(status)));
3735 TALLOC_FREE(result);
3736 return status;
3739 status = rpc_pipe_bind(result, auth);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3742 TALLOC_FREE(result);
3743 return status;
3746 result->transport->transport = NCACN_INTERNAL;
3748 *presult = result;
3749 return NT_STATUS_OK;
3752 /****************************************************************************
3753 Open a pipe to a remote server.
3754 ****************************************************************************/
3756 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3757 enum dcerpc_transport_t transport,
3758 const struct ndr_syntax_id *interface,
3759 struct rpc_pipe_client **presult)
3761 switch (transport) {
3762 case NCACN_IP_TCP:
3763 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3764 presult);
3765 case NCACN_NP:
3766 return rpc_pipe_open_np(cli, interface, presult);
3767 default:
3768 return NT_STATUS_NOT_IMPLEMENTED;
3772 /****************************************************************************
3773 Open a named pipe to an SMB server and bind anonymously.
3774 ****************************************************************************/
3776 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3777 enum dcerpc_transport_t transport,
3778 const struct ndr_syntax_id *interface,
3779 struct rpc_pipe_client **presult)
3781 struct rpc_pipe_client *result;
3782 struct cli_pipe_auth_data *auth;
3783 NTSTATUS status;
3785 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3786 if (!NT_STATUS_IS_OK(status)) {
3787 return status;
3790 status = rpccli_anon_bind_data(result, &auth);
3791 if (!NT_STATUS_IS_OK(status)) {
3792 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3793 nt_errstr(status)));
3794 TALLOC_FREE(result);
3795 return status;
3799 * This is a bit of an abstraction violation due to the fact that an
3800 * anonymous bind on an authenticated SMB inherits the user/domain
3801 * from the enclosing SMB creds
3804 TALLOC_FREE(auth->user_name);
3805 TALLOC_FREE(auth->domain);
3807 auth->user_name = talloc_strdup(auth, cli->user_name);
3808 auth->domain = talloc_strdup(auth, cli->domain);
3809 auth->user_session_key = data_blob_talloc(auth,
3810 cli->user_session_key.data,
3811 cli->user_session_key.length);
3813 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3814 TALLOC_FREE(result);
3815 return NT_STATUS_NO_MEMORY;
3818 status = rpc_pipe_bind(result, auth);
3819 if (!NT_STATUS_IS_OK(status)) {
3820 int lvl = 0;
3821 if (ndr_syntax_id_equal(interface,
3822 &ndr_table_dssetup.syntax_id)) {
3823 /* non AD domains just don't have this pipe, avoid
3824 * level 0 statement in that case - gd */
3825 lvl = 3;
3827 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3828 "%s failed with error %s\n",
3829 get_pipe_name_from_syntax(talloc_tos(), interface),
3830 nt_errstr(status) ));
3831 TALLOC_FREE(result);
3832 return status;
3835 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3836 "%s and bound anonymously.\n",
3837 get_pipe_name_from_syntax(talloc_tos(), interface),
3838 cli->desthost));
3840 *presult = result;
3841 return NT_STATUS_OK;
3844 /****************************************************************************
3845 ****************************************************************************/
3847 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3848 const struct ndr_syntax_id *interface,
3849 struct rpc_pipe_client **presult)
3851 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3852 interface, presult);
3855 /****************************************************************************
3856 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3857 ****************************************************************************/
3859 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3860 const struct ndr_syntax_id *interface,
3861 enum dcerpc_transport_t transport,
3862 enum pipe_auth_type auth_type,
3863 enum dcerpc_AuthLevel auth_level,
3864 const char *domain,
3865 const char *username,
3866 const char *password,
3867 struct rpc_pipe_client **presult)
3869 struct rpc_pipe_client *result;
3870 struct cli_pipe_auth_data *auth;
3871 NTSTATUS status;
3873 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3874 if (!NT_STATUS_IS_OK(status)) {
3875 return status;
3878 status = rpccli_ntlmssp_bind_data(
3879 result, auth_type, auth_level, domain, username,
3880 password, &auth);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3883 nt_errstr(status)));
3884 goto err;
3887 status = rpc_pipe_bind(result, auth);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3890 nt_errstr(status) ));
3891 goto err;
3894 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3895 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3896 get_pipe_name_from_syntax(talloc_tos(), interface),
3897 cli->desthost, domain, username ));
3899 *presult = result;
3900 return NT_STATUS_OK;
3902 err:
3904 TALLOC_FREE(result);
3905 return status;
3908 /****************************************************************************
3909 External interface.
3910 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3911 ****************************************************************************/
3913 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3914 const struct ndr_syntax_id *interface,
3915 enum dcerpc_transport_t transport,
3916 enum dcerpc_AuthLevel auth_level,
3917 const char *domain,
3918 const char *username,
3919 const char *password,
3920 struct rpc_pipe_client **presult)
3922 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3923 interface,
3924 transport,
3925 PIPE_AUTH_TYPE_NTLMSSP,
3926 auth_level,
3927 domain,
3928 username,
3929 password,
3930 presult);
3933 /****************************************************************************
3934 External interface.
3935 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3936 ****************************************************************************/
3938 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3939 const struct ndr_syntax_id *interface,
3940 enum dcerpc_transport_t transport,
3941 enum dcerpc_AuthLevel auth_level,
3942 const char *domain,
3943 const char *username,
3944 const char *password,
3945 struct rpc_pipe_client **presult)
3947 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3948 interface,
3949 transport,
3950 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3951 auth_level,
3952 domain,
3953 username,
3954 password,
3955 presult);
3958 /****************************************************************************
3959 Get a the schannel session key out of an already opened netlogon pipe.
3960 ****************************************************************************/
3961 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3962 struct cli_state *cli,
3963 const char *domain,
3964 uint32 *pneg_flags)
3966 enum netr_SchannelType sec_chan_type = 0;
3967 unsigned char machine_pwd[16];
3968 const char *machine_account;
3969 NTSTATUS status;
3971 /* Get the machine account credentials from secrets.tdb. */
3972 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3973 &sec_chan_type))
3975 DEBUG(0, ("get_schannel_session_key: could not fetch "
3976 "trust account password for domain '%s'\n",
3977 domain));
3978 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3981 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3982 cli->desthost, /* server name */
3983 domain, /* domain */
3984 global_myname(), /* client name */
3985 machine_account, /* machine account name */
3986 machine_pwd,
3987 sec_chan_type,
3988 pneg_flags);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 DEBUG(3, ("get_schannel_session_key_common: "
3992 "rpccli_netlogon_setup_creds failed with result %s "
3993 "to server %s, domain %s, machine account %s.\n",
3994 nt_errstr(status), cli->desthost, domain,
3995 machine_account ));
3996 return status;
3999 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
4000 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
4001 cli->desthost));
4002 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4005 return NT_STATUS_OK;;
4008 /****************************************************************************
4009 Open a netlogon pipe and get the schannel session key.
4010 Now exposed to external callers.
4011 ****************************************************************************/
4014 NTSTATUS get_schannel_session_key(struct cli_state *cli,
4015 const char *domain,
4016 uint32 *pneg_flags,
4017 struct rpc_pipe_client **presult)
4019 struct rpc_pipe_client *netlogon_pipe = NULL;
4020 NTSTATUS status;
4022 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
4023 &netlogon_pipe);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 return status;
4028 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4029 pneg_flags);
4030 if (!NT_STATUS_IS_OK(status)) {
4031 TALLOC_FREE(netlogon_pipe);
4032 return status;
4035 *presult = netlogon_pipe;
4036 return NT_STATUS_OK;
4039 /****************************************************************************
4040 External interface.
4041 Open a named pipe to an SMB server and bind using schannel (bind type 68)
4042 using session_key. sign and seal.
4044 The *pdc will be stolen onto this new pipe
4045 ****************************************************************************/
4047 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
4048 const struct ndr_syntax_id *interface,
4049 enum dcerpc_transport_t transport,
4050 enum dcerpc_AuthLevel auth_level,
4051 const char *domain,
4052 struct netlogon_creds_CredentialState **pdc,
4053 struct rpc_pipe_client **presult)
4055 struct rpc_pipe_client *result;
4056 struct cli_pipe_auth_data *auth;
4057 NTSTATUS status;
4059 status = cli_rpc_pipe_open(cli, transport, interface, &result);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 return status;
4064 status = rpccli_schannel_bind_data(result, domain, auth_level,
4065 *pdc, &auth);
4066 if (!NT_STATUS_IS_OK(status)) {
4067 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4068 nt_errstr(status)));
4069 TALLOC_FREE(result);
4070 return status;
4073 status = rpc_pipe_bind(result, auth);
4074 if (!NT_STATUS_IS_OK(status)) {
4075 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4076 "cli_rpc_pipe_bind failed with error %s\n",
4077 nt_errstr(status) ));
4078 TALLOC_FREE(result);
4079 return status;
4083 * The credentials on a new netlogon pipe are the ones we are passed
4084 * in - reference them in
4086 result->dc = talloc_move(result, pdc);
4088 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4089 "for domain %s and bound using schannel.\n",
4090 get_pipe_name_from_syntax(talloc_tos(), interface),
4091 cli->desthost, domain ));
4093 *presult = result;
4094 return NT_STATUS_OK;
4097 /****************************************************************************
4098 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4099 Fetch the session key ourselves using a temporary netlogon pipe. This
4100 version uses an ntlmssp auth bound netlogon pipe to get the key.
4101 ****************************************************************************/
4103 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4104 const char *domain,
4105 const char *username,
4106 const char *password,
4107 uint32 *pneg_flags,
4108 struct rpc_pipe_client **presult)
4110 struct rpc_pipe_client *netlogon_pipe = NULL;
4111 NTSTATUS status;
4113 status = cli_rpc_pipe_open_spnego_ntlmssp(
4114 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4115 DCERPC_AUTH_LEVEL_PRIVACY,
4116 domain, username, password, &netlogon_pipe);
4117 if (!NT_STATUS_IS_OK(status)) {
4118 return status;
4121 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4122 pneg_flags);
4123 if (!NT_STATUS_IS_OK(status)) {
4124 TALLOC_FREE(netlogon_pipe);
4125 return status;
4128 *presult = netlogon_pipe;
4129 return NT_STATUS_OK;
4132 /****************************************************************************
4133 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4134 Fetch the session key ourselves using a temporary netlogon pipe. This version
4135 uses an ntlmssp bind to get the session key.
4136 ****************************************************************************/
4138 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4139 const struct ndr_syntax_id *interface,
4140 enum dcerpc_transport_t transport,
4141 enum dcerpc_AuthLevel auth_level,
4142 const char *domain,
4143 const char *username,
4144 const char *password,
4145 struct rpc_pipe_client **presult)
4147 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4148 struct rpc_pipe_client *netlogon_pipe = NULL;
4149 struct rpc_pipe_client *result = NULL;
4150 NTSTATUS status;
4152 status = get_schannel_session_key_auth_ntlmssp(
4153 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4156 "key from server %s for domain %s.\n",
4157 cli->desthost, domain ));
4158 return status;
4161 status = cli_rpc_pipe_open_schannel_with_key(
4162 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4163 &result);
4165 /* Now we've bound using the session key we can close the netlog pipe. */
4166 TALLOC_FREE(netlogon_pipe);
4168 if (NT_STATUS_IS_OK(status)) {
4169 *presult = result;
4171 return status;
4174 /****************************************************************************
4175 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4176 Fetch the session key ourselves using a temporary netlogon pipe.
4177 ****************************************************************************/
4179 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4180 const struct ndr_syntax_id *interface,
4181 enum dcerpc_transport_t transport,
4182 enum dcerpc_AuthLevel auth_level,
4183 const char *domain,
4184 struct rpc_pipe_client **presult)
4186 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4187 struct rpc_pipe_client *netlogon_pipe = NULL;
4188 struct rpc_pipe_client *result = NULL;
4189 NTSTATUS status;
4191 status = get_schannel_session_key(cli, domain, &neg_flags,
4192 &netlogon_pipe);
4193 if (!NT_STATUS_IS_OK(status)) {
4194 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4195 "key from server %s for domain %s.\n",
4196 cli->desthost, domain ));
4197 return status;
4200 status = cli_rpc_pipe_open_schannel_with_key(
4201 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4202 &result);
4204 /* Now we've bound using the session key we can close the netlog pipe. */
4205 TALLOC_FREE(netlogon_pipe);
4207 if (NT_STATUS_IS_OK(status)) {
4208 *presult = result;
4211 return status;
4214 /****************************************************************************
4215 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4216 The idea is this can be called with service_princ, username and password all
4217 NULL so long as the caller has a TGT.
4218 ****************************************************************************/
4220 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4221 const struct ndr_syntax_id *interface,
4222 enum dcerpc_AuthLevel auth_level,
4223 const char *service_princ,
4224 const char *username,
4225 const char *password,
4226 struct rpc_pipe_client **presult)
4228 #ifdef HAVE_KRB5
4229 struct rpc_pipe_client *result;
4230 struct cli_pipe_auth_data *auth;
4231 NTSTATUS status;
4233 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 return status;
4238 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4239 username, password, &auth);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4242 nt_errstr(status)));
4243 TALLOC_FREE(result);
4244 return status;
4247 status = rpc_pipe_bind(result, auth);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4250 "with error %s\n", nt_errstr(status)));
4251 TALLOC_FREE(result);
4252 return status;
4255 *presult = result;
4256 return NT_STATUS_OK;
4257 #else
4258 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4259 return NT_STATUS_NOT_IMPLEMENTED;
4260 #endif
4263 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4264 struct rpc_pipe_client *cli,
4265 DATA_BLOB *session_key)
4267 if (!session_key || !cli) {
4268 return NT_STATUS_INVALID_PARAMETER;
4271 if (!cli->auth) {
4272 return NT_STATUS_INVALID_PARAMETER;
4275 switch (cli->auth->auth_type) {
4276 case PIPE_AUTH_TYPE_SCHANNEL:
4277 *session_key = data_blob_talloc(mem_ctx,
4278 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4279 break;
4280 case PIPE_AUTH_TYPE_NTLMSSP:
4281 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4282 *session_key = data_blob_talloc(mem_ctx,
4283 cli->auth->a_u.ntlmssp_state->session_key.data,
4284 cli->auth->a_u.ntlmssp_state->session_key.length);
4285 break;
4286 case PIPE_AUTH_TYPE_KRB5:
4287 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4288 *session_key = data_blob_talloc(mem_ctx,
4289 cli->auth->a_u.kerberos_auth->session_key.data,
4290 cli->auth->a_u.kerberos_auth->session_key.length);
4291 break;
4292 case PIPE_AUTH_TYPE_NONE:
4293 *session_key = data_blob_talloc(mem_ctx,
4294 cli->auth->user_session_key.data,
4295 cli->auth->user_session_key.length);
4296 break;
4297 default:
4298 return NT_STATUS_NO_USER_SESSION_KEY;
4301 return NT_STATUS_OK;