s3-lsa: Fix static list of luids in our privileges implementation.
[Samba/ekacnet.git] / source3 / rpc_client / cli_pipe.c
blobe248133de34d35f7f2c79b0f70d6ab358ff7e312
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 "../librpc/gen_ndr/ndr_lsa.h"
24 #include "../librpc/gen_ndr/ndr_dssetup.h"
25 #include "../librpc/gen_ndr/ndr_samr.h"
26 #include "../librpc/gen_ndr/ndr_netlogon.h"
27 #include "../librpc/gen_ndr/ndr_srvsvc.h"
28 #include "../librpc/gen_ndr/ndr_wkssvc.h"
29 #include "../librpc/gen_ndr/ndr_winreg.h"
30 #include "../librpc/gen_ndr/ndr_spoolss.h"
31 #include "../librpc/gen_ndr/ndr_dfs.h"
32 #include "../librpc/gen_ndr/ndr_echo.h"
33 #include "../librpc/gen_ndr/ndr_initshutdown.h"
34 #include "../librpc/gen_ndr/ndr_svcctl.h"
35 #include "../librpc/gen_ndr/ndr_eventlog.h"
36 #include "../librpc/gen_ndr/ndr_ntsvcs.h"
37 #include "../librpc/gen_ndr/ndr_epmapper.h"
38 #include "../librpc/gen_ndr/ndr_drsuapi.h"
39 #include "../libcli/auth/schannel.h"
40 #include "../libcli/auth/spnego.h"
41 #include "smb_krb5.h"
42 #include "../libcli/auth/ntlmssp.h"
43 #include "rpc_client/cli_netlogon.h"
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_RPC_CLI
48 static const char *get_pipe_name_from_iface(
49 TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
51 int i;
52 const struct ndr_interface_string_array *ep = interface->endpoints;
53 char *p;
55 for (i=0; i<ep->count; i++) {
56 if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
57 break;
60 if (i == ep->count) {
61 return NULL;
65 * extract the pipe name without \\pipe from for example
66 * ncacn_np:[\\pipe\\epmapper]
68 p = strchr(ep->names[i]+15, ']');
69 if (p == NULL) {
70 return "PIPE";
72 return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
75 static const struct ndr_interface_table **interfaces;
77 bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
79 int num_interfaces = talloc_array_length(interfaces);
80 const struct ndr_interface_table **tmp;
81 int i;
83 for (i=0; i<num_interfaces; i++) {
84 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
85 &interface->syntax_id)) {
86 return true;
90 tmp = talloc_realloc(NULL, interfaces,
91 const struct ndr_interface_table *,
92 num_interfaces + 1);
93 if (tmp == NULL) {
94 DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
95 return false;
97 interfaces = tmp;
98 interfaces[num_interfaces] = interface;
99 return true;
102 static bool initialize_interfaces(void)
104 if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
105 return false;
107 if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
108 return false;
110 if (!smb_register_ndr_interface(&ndr_table_samr)) {
111 return false;
113 if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
114 return false;
116 if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
117 return false;
119 if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
120 return false;
122 if (!smb_register_ndr_interface(&ndr_table_winreg)) {
123 return false;
125 if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
126 return false;
128 if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
129 return false;
131 if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
132 return false;
134 if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
135 return false;
137 if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
138 return false;
140 if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
141 return false;
143 if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
144 return false;
146 if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
147 return false;
149 if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
150 return false;
152 return true;
155 const struct ndr_interface_table *get_iface_from_syntax(
156 const struct ndr_syntax_id *syntax)
158 int num_interfaces;
159 int i;
161 if (interfaces == NULL) {
162 if (!initialize_interfaces()) {
163 return NULL;
166 num_interfaces = talloc_array_length(interfaces);
168 for (i=0; i<num_interfaces; i++) {
169 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
170 return interfaces[i];
174 return NULL;
177 /****************************************************************************
178 Return the pipe name from the interface.
179 ****************************************************************************/
181 const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
182 const struct ndr_syntax_id *syntax)
184 const struct ndr_interface_table *interface;
185 char *guid_str;
186 const char *result;
188 interface = get_iface_from_syntax(syntax);
189 if (interface != NULL) {
190 result = get_pipe_name_from_iface(mem_ctx, interface);
191 if (result != NULL) {
192 return result;
197 * Here we should ask \\epmapper, but for now our code is only
198 * interested in the known pipes mentioned in pipe_names[]
201 guid_str = GUID_string(talloc_tos(), &syntax->uuid);
202 if (guid_str == NULL) {
203 return NULL;
205 result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
206 (int)syntax->if_version);
207 TALLOC_FREE(guid_str);
209 if (result == NULL) {
210 return "PIPE";
212 return result;
215 /********************************************************************
216 Map internal value to wire value.
217 ********************************************************************/
219 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
221 switch (auth_type) {
223 case PIPE_AUTH_TYPE_NONE:
224 return DCERPC_AUTH_TYPE_NONE;
226 case PIPE_AUTH_TYPE_NTLMSSP:
227 return DCERPC_AUTH_TYPE_NTLMSSP;
229 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
230 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
231 return DCERPC_AUTH_TYPE_SPNEGO;
233 case PIPE_AUTH_TYPE_SCHANNEL:
234 return DCERPC_AUTH_TYPE_SCHANNEL;
236 case PIPE_AUTH_TYPE_KRB5:
237 return DCERPC_AUTH_TYPE_KRB5;
239 default:
240 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
241 "auth type %u\n",
242 (unsigned int)auth_type ));
243 break;
245 return -1;
248 /********************************************************************
249 Pipe description for a DEBUG
250 ********************************************************************/
251 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
252 struct rpc_pipe_client *cli)
254 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
255 if (result == NULL) {
256 return "pipe";
258 return result;
261 /********************************************************************
262 Rpc pipe call id.
263 ********************************************************************/
265 static uint32 get_rpc_call_id(void)
267 static uint32 call_id = 0;
268 return ++call_id;
272 * Realloc pdu to have a least "size" bytes
275 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
277 size_t extra_size;
279 if (prs_data_size(pdu) >= size) {
280 return true;
283 extra_size = size - prs_data_size(pdu);
285 if (!prs_force_grow(pdu, extra_size)) {
286 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
287 "%d bytes.\n", (int)extra_size));
288 return false;
291 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
292 (int)extra_size, prs_data_size(pdu)));
293 return true;
297 /*******************************************************************
298 Use SMBreadX to get rest of one fragment's worth of rpc data.
299 Reads the whole size or give an error message
300 ********************************************************************/
302 struct rpc_read_state {
303 struct event_context *ev;
304 struct rpc_cli_transport *transport;
305 uint8_t *data;
306 size_t size;
307 size_t num_read;
310 static void rpc_read_done(struct tevent_req *subreq);
312 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
313 struct event_context *ev,
314 struct rpc_cli_transport *transport,
315 uint8_t *data, size_t size)
317 struct tevent_req *req, *subreq;
318 struct rpc_read_state *state;
320 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
321 if (req == NULL) {
322 return NULL;
324 state->ev = ev;
325 state->transport = transport;
326 state->data = data;
327 state->size = size;
328 state->num_read = 0;
330 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
332 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
333 transport->priv);
334 if (subreq == NULL) {
335 goto fail;
337 tevent_req_set_callback(subreq, rpc_read_done, req);
338 return req;
340 fail:
341 TALLOC_FREE(req);
342 return NULL;
345 static void rpc_read_done(struct tevent_req *subreq)
347 struct tevent_req *req = tevent_req_callback_data(
348 subreq, struct tevent_req);
349 struct rpc_read_state *state = tevent_req_data(
350 req, struct rpc_read_state);
351 NTSTATUS status;
352 ssize_t received;
354 status = state->transport->read_recv(subreq, &received);
355 TALLOC_FREE(subreq);
356 if (!NT_STATUS_IS_OK(status)) {
357 tevent_req_nterror(req, status);
358 return;
361 state->num_read += received;
362 if (state->num_read == state->size) {
363 tevent_req_done(req);
364 return;
367 subreq = state->transport->read_send(state, state->ev,
368 state->data + state->num_read,
369 state->size - state->num_read,
370 state->transport->priv);
371 if (tevent_req_nomem(subreq, req)) {
372 return;
374 tevent_req_set_callback(subreq, rpc_read_done, req);
377 static NTSTATUS rpc_read_recv(struct tevent_req *req)
379 return tevent_req_simple_recv_ntstatus(req);
382 struct rpc_write_state {
383 struct event_context *ev;
384 struct rpc_cli_transport *transport;
385 const uint8_t *data;
386 size_t size;
387 size_t num_written;
390 static void rpc_write_done(struct tevent_req *subreq);
392 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
393 struct event_context *ev,
394 struct rpc_cli_transport *transport,
395 const uint8_t *data, size_t size)
397 struct tevent_req *req, *subreq;
398 struct rpc_write_state *state;
400 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
401 if (req == NULL) {
402 return NULL;
404 state->ev = ev;
405 state->transport = transport;
406 state->data = data;
407 state->size = size;
408 state->num_written = 0;
410 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
412 subreq = transport->write_send(state, ev, data, size, transport->priv);
413 if (subreq == NULL) {
414 goto fail;
416 tevent_req_set_callback(subreq, rpc_write_done, req);
417 return req;
418 fail:
419 TALLOC_FREE(req);
420 return NULL;
423 static void rpc_write_done(struct tevent_req *subreq)
425 struct tevent_req *req = tevent_req_callback_data(
426 subreq, struct tevent_req);
427 struct rpc_write_state *state = tevent_req_data(
428 req, struct rpc_write_state);
429 NTSTATUS status;
430 ssize_t written;
432 status = state->transport->write_recv(subreq, &written);
433 TALLOC_FREE(subreq);
434 if (!NT_STATUS_IS_OK(status)) {
435 tevent_req_nterror(req, status);
436 return;
439 state->num_written += written;
441 if (state->num_written == state->size) {
442 tevent_req_done(req);
443 return;
446 subreq = state->transport->write_send(state, state->ev,
447 state->data + state->num_written,
448 state->size - state->num_written,
449 state->transport->priv);
450 if (tevent_req_nomem(subreq, req)) {
451 return;
453 tevent_req_set_callback(subreq, rpc_write_done, req);
456 static NTSTATUS rpc_write_recv(struct tevent_req *req)
458 return tevent_req_simple_recv_ntstatus(req);
462 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
463 struct rpc_hdr_info *prhdr,
464 prs_struct *pdu)
467 * This next call sets the endian bit correctly in current_pdu. We
468 * will propagate this to rbuf later.
471 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, pdu, 0)) {
472 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
473 return NT_STATUS_BUFFER_TOO_SMALL;
476 if (prhdr->frag_len > cli->max_recv_frag) {
477 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
478 " we only allow %d\n", (int)prhdr->frag_len,
479 (int)cli->max_recv_frag));
480 return NT_STATUS_BUFFER_TOO_SMALL;
483 return NT_STATUS_OK;
486 /****************************************************************************
487 Try and get a PDU's worth of data from current_pdu. If not, then read more
488 from the wire.
489 ****************************************************************************/
491 struct get_complete_frag_state {
492 struct event_context *ev;
493 struct rpc_pipe_client *cli;
494 struct rpc_hdr_info *prhdr;
495 prs_struct *pdu;
498 static void get_complete_frag_got_header(struct tevent_req *subreq);
499 static void get_complete_frag_got_rest(struct tevent_req *subreq);
501 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
502 struct event_context *ev,
503 struct rpc_pipe_client *cli,
504 struct rpc_hdr_info *prhdr,
505 prs_struct *pdu)
507 struct tevent_req *req, *subreq;
508 struct get_complete_frag_state *state;
509 uint32_t pdu_len;
510 NTSTATUS status;
512 req = tevent_req_create(mem_ctx, &state,
513 struct get_complete_frag_state);
514 if (req == NULL) {
515 return NULL;
517 state->ev = ev;
518 state->cli = cli;
519 state->prhdr = prhdr;
520 state->pdu = pdu;
522 pdu_len = prs_data_size(pdu);
523 if (pdu_len < RPC_HEADER_LEN) {
524 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
525 status = NT_STATUS_NO_MEMORY;
526 goto post_status;
528 subreq = rpc_read_send(
529 state, state->ev,
530 state->cli->transport,
531 (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
532 RPC_HEADER_LEN - pdu_len);
533 if (subreq == NULL) {
534 status = NT_STATUS_NO_MEMORY;
535 goto post_status;
537 tevent_req_set_callback(subreq, get_complete_frag_got_header,
538 req);
539 return req;
542 status = parse_rpc_header(cli, prhdr, pdu);
543 if (!NT_STATUS_IS_OK(status)) {
544 goto post_status;
548 * Ensure we have frag_len bytes of data.
550 if (pdu_len < prhdr->frag_len) {
551 if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
552 status = NT_STATUS_NO_MEMORY;
553 goto post_status;
555 subreq = rpc_read_send(state, state->ev,
556 state->cli->transport,
557 (uint8_t *)(prs_data_p(pdu) + pdu_len),
558 prhdr->frag_len - pdu_len);
559 if (subreq == NULL) {
560 status = NT_STATUS_NO_MEMORY;
561 goto post_status;
563 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
564 req);
565 return req;
568 status = NT_STATUS_OK;
569 post_status:
570 if (NT_STATUS_IS_OK(status)) {
571 tevent_req_done(req);
572 } else {
573 tevent_req_nterror(req, status);
575 return tevent_req_post(req, ev);
578 static void get_complete_frag_got_header(struct tevent_req *subreq)
580 struct tevent_req *req = tevent_req_callback_data(
581 subreq, struct tevent_req);
582 struct get_complete_frag_state *state = tevent_req_data(
583 req, struct get_complete_frag_state);
584 NTSTATUS status;
586 status = rpc_read_recv(subreq);
587 TALLOC_FREE(subreq);
588 if (!NT_STATUS_IS_OK(status)) {
589 tevent_req_nterror(req, status);
590 return;
593 status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
594 if (!NT_STATUS_IS_OK(status)) {
595 tevent_req_nterror(req, status);
596 return;
599 if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
600 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
601 return;
605 * We're here in this piece of code because we've read exactly
606 * RPC_HEADER_LEN bytes into state->pdu.
609 subreq = rpc_read_send(
610 state, state->ev, state->cli->transport,
611 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
612 state->prhdr->frag_len - RPC_HEADER_LEN);
613 if (tevent_req_nomem(subreq, req)) {
614 return;
616 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
619 static void get_complete_frag_got_rest(struct tevent_req *subreq)
621 struct tevent_req *req = tevent_req_callback_data(
622 subreq, struct tevent_req);
623 NTSTATUS status;
625 status = rpc_read_recv(subreq);
626 TALLOC_FREE(subreq);
627 if (!NT_STATUS_IS_OK(status)) {
628 tevent_req_nterror(req, status);
629 return;
631 tevent_req_done(req);
634 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
636 return tevent_req_simple_recv_ntstatus(req);
639 /****************************************************************************
640 NTLMSSP specific sign/seal.
641 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
642 In fact I should probably abstract these into identical pieces of code... JRA.
643 ****************************************************************************/
645 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
646 prs_struct *current_pdu,
647 uint8 *p_ss_padding_len)
649 RPC_HDR_AUTH auth_info;
650 uint32 save_offset = prs_offset(current_pdu);
651 uint32 auth_len = prhdr->auth_len;
652 struct ntlmssp_state *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
653 unsigned char *data = NULL;
654 size_t data_len;
655 unsigned char *full_packet_data = NULL;
656 size_t full_packet_data_len;
657 DATA_BLOB auth_blob;
658 NTSTATUS status;
660 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
661 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
662 return NT_STATUS_OK;
665 if (!ntlmssp_state) {
666 return NT_STATUS_INVALID_PARAMETER;
669 /* Ensure there's enough data for an authenticated response. */
670 if (auth_len > RPC_MAX_PDU_FRAG_LEN ||
671 prhdr->frag_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
672 RPC_HDR_AUTH_LEN + auth_len) {
673 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
674 (unsigned int)auth_len ));
675 return NT_STATUS_BUFFER_TOO_SMALL;
679 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
680 * after the RPC header.
681 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
682 * functions as NTLMv2 checks the rpc headers also.
685 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
686 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
688 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
689 full_packet_data_len = prhdr->frag_len - auth_len;
691 /* Pull the auth header and the following data into a blob. */
692 /* NB. The offset of the auth_header is relative to the *end*
693 * of the packet, not the start. */
694 if(!prs_set_offset(current_pdu, prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
695 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
696 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
697 return NT_STATUS_BUFFER_TOO_SMALL;
700 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
701 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
702 return NT_STATUS_BUFFER_TOO_SMALL;
705 /* Ensure auth_pad_len fits into the packet. */
706 if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
707 RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
708 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
709 "too large (%u), auth_len (%u), frag_len = (%u).\n",
710 (unsigned int)auth_info.auth_pad_len,
711 (unsigned int)auth_len,
712 (unsigned int)prhdr->frag_len ));
713 return NT_STATUS_BUFFER_TOO_SMALL;
717 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
718 auth_blob.length = auth_len;
720 switch (cli->auth->auth_level) {
721 case DCERPC_AUTH_LEVEL_PRIVACY:
722 /* Data is encrypted. */
723 status = ntlmssp_unseal_packet(ntlmssp_state,
724 data, data_len,
725 full_packet_data,
726 full_packet_data_len,
727 &auth_blob);
728 if (!NT_STATUS_IS_OK(status)) {
729 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
730 "packet from %s. Error was %s.\n",
731 rpccli_pipe_txt(talloc_tos(), cli),
732 nt_errstr(status) ));
733 return status;
735 break;
736 case DCERPC_AUTH_LEVEL_INTEGRITY:
737 /* Data is signed. */
738 status = ntlmssp_check_packet(ntlmssp_state,
739 data, data_len,
740 full_packet_data,
741 full_packet_data_len,
742 &auth_blob);
743 if (!NT_STATUS_IS_OK(status)) {
744 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
745 "packet from %s. Error was %s.\n",
746 rpccli_pipe_txt(talloc_tos(), cli),
747 nt_errstr(status) ));
748 return status;
750 break;
751 default:
752 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
753 "auth level %d\n", cli->auth->auth_level));
754 return NT_STATUS_INVALID_INFO_CLASS;
758 * Return the current pointer to the data offset.
761 if(!prs_set_offset(current_pdu, save_offset)) {
762 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
763 (unsigned int)save_offset ));
764 return NT_STATUS_BUFFER_TOO_SMALL;
768 * Remember the padding length. We must remove it from the real data
769 * stream once the sign/seal is done.
772 *p_ss_padding_len = auth_info.auth_pad_len;
774 return NT_STATUS_OK;
777 /****************************************************************************
778 schannel specific sign/seal.
779 ****************************************************************************/
781 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
782 prs_struct *current_pdu,
783 uint8 *p_ss_padding_len)
785 RPC_HDR_AUTH auth_info;
786 uint32 auth_len = prhdr->auth_len;
787 uint32 save_offset = prs_offset(current_pdu);
788 struct schannel_state *schannel_auth =
789 cli->auth->a_u.schannel_auth;
790 uint8_t *data;
791 uint32 data_len;
792 DATA_BLOB blob;
793 NTSTATUS status;
795 if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
796 || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
797 return NT_STATUS_OK;
800 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
801 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
802 return NT_STATUS_INVALID_PARAMETER;
805 if (!schannel_auth) {
806 return NT_STATUS_INVALID_PARAMETER;
809 /* Ensure there's enough data for an authenticated response. */
810 if ((auth_len > RPC_MAX_PDU_FRAG_LEN) ||
811 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
812 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
813 (unsigned int)auth_len ));
814 return NT_STATUS_INVALID_PARAMETER;
817 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
819 /* Pull the auth header and the following data into a blob. */
820 /* NB. The offset of the auth_header is relative to the *end*
821 * of the packet, not the start. */
822 if(!prs_set_offset(current_pdu,
823 prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
824 DEBUG(0,("cli_pipe_verify_schannel: cannot move "
825 "offset to %u.\n",
826 (unsigned int)(prhdr->frag_len -
827 RPC_HDR_AUTH_LEN - auth_len) ));
828 return NT_STATUS_BUFFER_TOO_SMALL;
831 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
832 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
833 return NT_STATUS_BUFFER_TOO_SMALL;
836 /* Ensure auth_pad_len fits into the packet. */
837 if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
838 RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
839 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
840 "too large (%u), auth_len (%u), frag_len = (%u).\n",
841 (unsigned int)auth_info.auth_pad_len,
842 (unsigned int)auth_len,
843 (unsigned int)prhdr->frag_len ));
844 return NT_STATUS_BUFFER_TOO_SMALL;
847 if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
848 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
849 auth_info.auth_type));
850 return NT_STATUS_BUFFER_TOO_SMALL;
853 blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), auth_len);
855 if (DEBUGLEVEL >= 10) {
856 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
859 data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
861 switch (cli->auth->auth_level) {
862 case DCERPC_AUTH_LEVEL_PRIVACY:
863 status = netsec_incoming_packet(schannel_auth,
864 talloc_tos(),
865 true,
866 data,
867 data_len,
868 &blob);
869 break;
870 case DCERPC_AUTH_LEVEL_INTEGRITY:
871 status = netsec_incoming_packet(schannel_auth,
872 talloc_tos(),
873 false,
874 data,
875 data_len,
876 &blob);
877 break;
878 default:
879 status = NT_STATUS_INTERNAL_ERROR;
880 break;
883 if (!NT_STATUS_IS_OK(status)) {
884 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
885 "Connection to %s (%s).\n",
886 rpccli_pipe_txt(talloc_tos(), cli),
887 nt_errstr(status)));
888 return NT_STATUS_INVALID_PARAMETER;
892 * Return the current pointer to the data offset.
895 if(!prs_set_offset(current_pdu, save_offset)) {
896 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
897 (unsigned int)save_offset ));
898 return NT_STATUS_BUFFER_TOO_SMALL;
902 * Remember the padding length. We must remove it from the real data
903 * stream once the sign/seal is done.
906 *p_ss_padding_len = auth_info.auth_pad_len;
908 return NT_STATUS_OK;
911 /****************************************************************************
912 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
913 ****************************************************************************/
915 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
916 prs_struct *current_pdu,
917 uint8 *p_ss_padding_len)
919 NTSTATUS ret = NT_STATUS_OK;
921 /* Paranioa checks for auth_len. */
922 if (prhdr->auth_len) {
923 if (prhdr->auth_len > prhdr->frag_len) {
924 return NT_STATUS_INVALID_PARAMETER;
927 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
928 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
929 /* Integer wrap attempt. */
930 return NT_STATUS_INVALID_PARAMETER;
935 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
938 switch(cli->auth->auth_type) {
939 case PIPE_AUTH_TYPE_NONE:
940 if (prhdr->auth_len) {
941 DEBUG(3, ("cli_pipe_validate_rpc_response: "
942 "Connection to %s - got non-zero "
943 "auth len %u.\n",
944 rpccli_pipe_txt(talloc_tos(), cli),
945 (unsigned int)prhdr->auth_len ));
946 return NT_STATUS_INVALID_PARAMETER;
948 break;
950 case PIPE_AUTH_TYPE_NTLMSSP:
951 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
952 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
953 if (!NT_STATUS_IS_OK(ret)) {
954 return ret;
956 break;
958 case PIPE_AUTH_TYPE_SCHANNEL:
959 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
960 if (!NT_STATUS_IS_OK(ret)) {
961 return ret;
963 break;
965 case PIPE_AUTH_TYPE_KRB5:
966 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
967 default:
968 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
969 "to %s - unknown internal auth type %u.\n",
970 rpccli_pipe_txt(talloc_tos(), cli),
971 cli->auth->auth_type ));
972 return NT_STATUS_INVALID_INFO_CLASS;
975 return NT_STATUS_OK;
978 /****************************************************************************
979 Do basic authentication checks on an incoming pdu.
980 ****************************************************************************/
982 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
983 prs_struct *current_pdu,
984 uint8 expected_pkt_type,
985 char **ppdata,
986 uint32 *pdata_len,
987 prs_struct *return_data)
990 NTSTATUS ret = NT_STATUS_OK;
991 uint32 current_pdu_len = prs_data_size(current_pdu);
993 if (current_pdu_len != prhdr->frag_len) {
994 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
995 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
996 return NT_STATUS_INVALID_PARAMETER;
1000 * Point the return values at the real data including the RPC
1001 * header. Just in case the caller wants it.
1003 *ppdata = prs_data_p(current_pdu);
1004 *pdata_len = current_pdu_len;
1006 /* Ensure we have the correct type. */
1007 switch (prhdr->pkt_type) {
1008 case DCERPC_PKT_ALTER_RESP:
1009 case DCERPC_PKT_BIND_ACK:
1011 /* Alter context and bind ack share the same packet definitions. */
1012 break;
1015 case DCERPC_PKT_RESPONSE:
1017 RPC_HDR_RESP rhdr_resp;
1018 uint8 ss_padding_len = 0;
1020 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1021 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1022 return NT_STATUS_BUFFER_TOO_SMALL;
1025 /* Here's where we deal with incoming sign/seal. */
1026 ret = cli_pipe_validate_rpc_response(cli, prhdr,
1027 current_pdu, &ss_padding_len);
1028 if (!NT_STATUS_IS_OK(ret)) {
1029 return ret;
1032 /* Point the return values at the NDR data. Remember to remove any ss padding. */
1033 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1035 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
1036 return NT_STATUS_BUFFER_TOO_SMALL;
1039 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
1041 /* Remember to remove the auth footer. */
1042 if (prhdr->auth_len) {
1043 /* We've already done integer wrap tests on auth_len in
1044 cli_pipe_validate_rpc_response(). */
1045 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
1046 return NT_STATUS_BUFFER_TOO_SMALL;
1048 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
1051 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
1052 current_pdu_len, *pdata_len, ss_padding_len ));
1055 * If this is the first reply, and the allocation hint is reasonably, try and
1056 * set up the return_data parse_struct to the correct size.
1059 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
1060 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
1061 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
1062 "too large to allocate\n",
1063 (unsigned int)rhdr_resp.alloc_hint ));
1064 return NT_STATUS_NO_MEMORY;
1068 break;
1071 case DCERPC_PKT_BIND_NAK:
1072 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1073 "received from %s!\n",
1074 rpccli_pipe_txt(talloc_tos(), cli)));
1075 /* Use this for now... */
1076 return NT_STATUS_NETWORK_ACCESS_DENIED;
1078 case DCERPC_PKT_FAULT:
1080 RPC_HDR_RESP rhdr_resp;
1081 RPC_HDR_FAULT fault_resp;
1083 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1084 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1085 return NT_STATUS_BUFFER_TOO_SMALL;
1088 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
1089 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
1090 return NT_STATUS_BUFFER_TOO_SMALL;
1093 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1094 "code %s received from %s!\n",
1095 dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
1096 rpccli_pipe_txt(talloc_tos(), cli)));
1097 if (NT_STATUS_IS_OK(fault_resp.status)) {
1098 return NT_STATUS_UNSUCCESSFUL;
1099 } else {
1100 return fault_resp.status;
1104 default:
1105 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
1106 "from %s!\n",
1107 (unsigned int)prhdr->pkt_type,
1108 rpccli_pipe_txt(talloc_tos(), cli)));
1109 return NT_STATUS_INVALID_INFO_CLASS;
1112 if (prhdr->pkt_type != expected_pkt_type) {
1113 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1114 "got an unexpected RPC packet type - %u, not %u\n",
1115 rpccli_pipe_txt(talloc_tos(), cli),
1116 prhdr->pkt_type,
1117 expected_pkt_type));
1118 return NT_STATUS_INVALID_INFO_CLASS;
1121 /* Do this just before return - we don't want to modify any rpc header
1122 data before now as we may have needed to do cryptographic actions on
1123 it before. */
1125 if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) {
1126 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1127 "setting fragment first/last ON.\n"));
1128 prhdr->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST;
1131 return NT_STATUS_OK;
1134 /****************************************************************************
1135 Ensure we eat the just processed pdu from the current_pdu prs_struct.
1136 Normally the frag_len and buffer size will match, but on the first trans
1137 reply there is a theoretical chance that buffer size > frag_len, so we must
1138 deal with that.
1139 ****************************************************************************/
1141 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
1143 uint32 current_pdu_len = prs_data_size(current_pdu);
1145 if (current_pdu_len < prhdr->frag_len) {
1146 return NT_STATUS_BUFFER_TOO_SMALL;
1149 /* Common case. */
1150 if (current_pdu_len == (uint32)prhdr->frag_len) {
1151 prs_mem_free(current_pdu);
1152 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1153 /* Make current_pdu dynamic with no memory. */
1154 prs_give_memory(current_pdu, 0, 0, True);
1155 return NT_STATUS_OK;
1159 * Oh no ! More data in buffer than we processed in current pdu.
1160 * Cheat. Move the data down and shrink the buffer.
1163 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1164 current_pdu_len - prhdr->frag_len);
1166 /* Remember to set the read offset back to zero. */
1167 prs_set_offset(current_pdu, 0);
1169 /* Shrink the buffer. */
1170 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1171 return NT_STATUS_BUFFER_TOO_SMALL;
1174 return NT_STATUS_OK;
1177 /****************************************************************************
1178 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1179 ****************************************************************************/
1181 struct cli_api_pipe_state {
1182 struct event_context *ev;
1183 struct rpc_cli_transport *transport;
1184 uint8_t *rdata;
1185 uint32_t rdata_len;
1188 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1189 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1190 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1192 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1193 struct event_context *ev,
1194 struct rpc_cli_transport *transport,
1195 uint8_t *data, size_t data_len,
1196 uint32_t max_rdata_len)
1198 struct tevent_req *req, *subreq;
1199 struct cli_api_pipe_state *state;
1200 NTSTATUS status;
1202 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1203 if (req == NULL) {
1204 return NULL;
1206 state->ev = ev;
1207 state->transport = transport;
1209 if (max_rdata_len < RPC_HEADER_LEN) {
1211 * For a RPC reply we always need at least RPC_HEADER_LEN
1212 * bytes. We check this here because we will receive
1213 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1215 status = NT_STATUS_INVALID_PARAMETER;
1216 goto post_status;
1219 if (transport->trans_send != NULL) {
1220 subreq = transport->trans_send(state, ev, data, data_len,
1221 max_rdata_len, transport->priv);
1222 if (subreq == NULL) {
1223 goto fail;
1225 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1226 return req;
1230 * If the transport does not provide a "trans" routine, i.e. for
1231 * example the ncacn_ip_tcp transport, do the write/read step here.
1234 subreq = rpc_write_send(state, ev, transport, data, data_len);
1235 if (subreq == NULL) {
1236 goto fail;
1238 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1239 return req;
1241 status = NT_STATUS_INVALID_PARAMETER;
1243 post_status:
1244 tevent_req_nterror(req, status);
1245 return tevent_req_post(req, ev);
1246 fail:
1247 TALLOC_FREE(req);
1248 return NULL;
1251 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1253 struct tevent_req *req = tevent_req_callback_data(
1254 subreq, struct tevent_req);
1255 struct cli_api_pipe_state *state = tevent_req_data(
1256 req, struct cli_api_pipe_state);
1257 NTSTATUS status;
1259 status = state->transport->trans_recv(subreq, state, &state->rdata,
1260 &state->rdata_len);
1261 TALLOC_FREE(subreq);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 tevent_req_nterror(req, status);
1264 return;
1266 tevent_req_done(req);
1269 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1271 struct tevent_req *req = tevent_req_callback_data(
1272 subreq, struct tevent_req);
1273 struct cli_api_pipe_state *state = tevent_req_data(
1274 req, struct cli_api_pipe_state);
1275 NTSTATUS status;
1277 status = rpc_write_recv(subreq);
1278 TALLOC_FREE(subreq);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 tevent_req_nterror(req, status);
1281 return;
1284 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1285 if (tevent_req_nomem(state->rdata, req)) {
1286 return;
1290 * We don't need to use rpc_read_send here, the upper layer will cope
1291 * with a short read, transport->trans_send could also return less
1292 * than state->max_rdata_len.
1294 subreq = state->transport->read_send(state, state->ev, state->rdata,
1295 RPC_HEADER_LEN,
1296 state->transport->priv);
1297 if (tevent_req_nomem(subreq, req)) {
1298 return;
1300 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1303 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1305 struct tevent_req *req = tevent_req_callback_data(
1306 subreq, struct tevent_req);
1307 struct cli_api_pipe_state *state = tevent_req_data(
1308 req, struct cli_api_pipe_state);
1309 NTSTATUS status;
1310 ssize_t received;
1312 status = state->transport->read_recv(subreq, &received);
1313 TALLOC_FREE(subreq);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 tevent_req_nterror(req, status);
1316 return;
1318 state->rdata_len = received;
1319 tevent_req_done(req);
1322 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1323 uint8_t **prdata, uint32_t *prdata_len)
1325 struct cli_api_pipe_state *state = tevent_req_data(
1326 req, struct cli_api_pipe_state);
1327 NTSTATUS status;
1329 if (tevent_req_is_nterror(req, &status)) {
1330 return status;
1333 *prdata = talloc_move(mem_ctx, &state->rdata);
1334 *prdata_len = state->rdata_len;
1335 return NT_STATUS_OK;
1338 /****************************************************************************
1339 Send data on an rpc pipe via trans. The prs_struct data must be the last
1340 pdu fragment of an NDR data stream.
1342 Receive response data from an rpc pipe, which may be large...
1344 Read the first fragment: unfortunately have to use SMBtrans for the first
1345 bit, then SMBreadX for subsequent bits.
1347 If first fragment received also wasn't the last fragment, continue
1348 getting fragments until we _do_ receive the last fragment.
1350 Request/Response PDU's look like the following...
1352 |<------------------PDU len----------------------------------------------->|
1353 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1355 +------------+-----------------+-------------+---------------+-------------+
1356 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1357 +------------+-----------------+-------------+---------------+-------------+
1359 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1360 signing & sealing being negotiated.
1362 ****************************************************************************/
1364 struct rpc_api_pipe_state {
1365 struct event_context *ev;
1366 struct rpc_pipe_client *cli;
1367 uint8_t expected_pkt_type;
1369 prs_struct incoming_frag;
1370 struct rpc_hdr_info rhdr;
1372 prs_struct incoming_pdu; /* Incoming reply */
1373 uint32_t incoming_pdu_offset;
1376 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1378 prs_mem_free(&state->incoming_frag);
1379 prs_mem_free(&state->incoming_pdu);
1380 return 0;
1383 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1384 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1386 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1387 struct event_context *ev,
1388 struct rpc_pipe_client *cli,
1389 prs_struct *data, /* Outgoing PDU */
1390 uint8_t expected_pkt_type)
1392 struct tevent_req *req, *subreq;
1393 struct rpc_api_pipe_state *state;
1394 uint16_t max_recv_frag;
1395 NTSTATUS status;
1397 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1398 if (req == NULL) {
1399 return NULL;
1401 state->ev = ev;
1402 state->cli = cli;
1403 state->expected_pkt_type = expected_pkt_type;
1404 state->incoming_pdu_offset = 0;
1406 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1408 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1409 /* Make incoming_pdu dynamic with no memory. */
1410 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1412 talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1415 * Ensure we're not sending too much.
1417 if (prs_offset(data) > cli->max_xmit_frag) {
1418 status = NT_STATUS_INVALID_PARAMETER;
1419 goto post_status;
1422 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1424 max_recv_frag = cli->max_recv_frag;
1426 #if 0
1427 max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1428 #endif
1430 subreq = cli_api_pipe_send(state, ev, cli->transport,
1431 (uint8_t *)prs_data_p(data),
1432 prs_offset(data), max_recv_frag);
1433 if (subreq == NULL) {
1434 goto fail;
1436 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1437 return req;
1439 post_status:
1440 tevent_req_nterror(req, status);
1441 return tevent_req_post(req, ev);
1442 fail:
1443 TALLOC_FREE(req);
1444 return NULL;
1447 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1449 struct tevent_req *req = tevent_req_callback_data(
1450 subreq, struct tevent_req);
1451 struct rpc_api_pipe_state *state = tevent_req_data(
1452 req, struct rpc_api_pipe_state);
1453 NTSTATUS status;
1454 uint8_t *rdata = NULL;
1455 uint32_t rdata_len = 0;
1456 char *rdata_copy;
1458 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1459 TALLOC_FREE(subreq);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1462 tevent_req_nterror(req, status);
1463 return;
1466 if (rdata == NULL) {
1467 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1468 rpccli_pipe_txt(talloc_tos(), state->cli)));
1469 tevent_req_done(req);
1470 return;
1474 * Give the memory received from cli_trans as dynamic to the current
1475 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1476 * :-(
1478 rdata_copy = (char *)memdup(rdata, rdata_len);
1479 TALLOC_FREE(rdata);
1480 if (tevent_req_nomem(rdata_copy, req)) {
1481 return;
1483 prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
1485 /* Ensure we have enough data for a pdu. */
1486 subreq = get_complete_frag_send(state, state->ev, state->cli,
1487 &state->rhdr, &state->incoming_frag);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return;
1491 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1494 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1496 struct tevent_req *req = tevent_req_callback_data(
1497 subreq, struct tevent_req);
1498 struct rpc_api_pipe_state *state = tevent_req_data(
1499 req, struct rpc_api_pipe_state);
1500 NTSTATUS status;
1501 char *rdata = NULL;
1502 uint32_t rdata_len = 0;
1504 status = get_complete_frag_recv(subreq);
1505 TALLOC_FREE(subreq);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 DEBUG(5, ("get_complete_frag failed: %s\n",
1508 nt_errstr(status)));
1509 tevent_req_nterror(req, status);
1510 return;
1513 status = cli_pipe_validate_current_pdu(
1514 state->cli, &state->rhdr, &state->incoming_frag,
1515 state->expected_pkt_type, &rdata, &rdata_len,
1516 &state->incoming_pdu);
1518 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1519 (unsigned)prs_data_size(&state->incoming_frag),
1520 (unsigned)state->incoming_pdu_offset,
1521 nt_errstr(status)));
1523 if (!NT_STATUS_IS_OK(status)) {
1524 tevent_req_nterror(req, status);
1525 return;
1528 if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST)
1529 && (state->rhdr.pack_type[0] == 0)) {
1531 * Set the data type correctly for big-endian data on the
1532 * first packet.
1534 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1535 "big-endian.\n",
1536 rpccli_pipe_txt(talloc_tos(), state->cli)));
1537 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1540 * Check endianness on subsequent packets.
1542 if (state->incoming_frag.bigendian_data
1543 != state->incoming_pdu.bigendian_data) {
1544 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1545 "%s\n",
1546 state->incoming_pdu.bigendian_data?"big":"little",
1547 state->incoming_frag.bigendian_data?"big":"little"));
1548 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1549 return;
1552 /* Now copy the data portion out of the pdu into rbuf. */
1553 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1554 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1555 return;
1558 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1559 rdata, (size_t)rdata_len);
1560 state->incoming_pdu_offset += rdata_len;
1562 status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1563 &state->incoming_frag);
1564 if (!NT_STATUS_IS_OK(status)) {
1565 tevent_req_nterror(req, status);
1566 return;
1569 if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
1570 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1571 rpccli_pipe_txt(talloc_tos(), state->cli),
1572 (unsigned)prs_data_size(&state->incoming_pdu)));
1573 tevent_req_done(req);
1574 return;
1577 subreq = get_complete_frag_send(state, state->ev, state->cli,
1578 &state->rhdr, &state->incoming_frag);
1579 if (tevent_req_nomem(subreq, req)) {
1580 return;
1582 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1585 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1586 prs_struct *reply_pdu)
1588 struct rpc_api_pipe_state *state = tevent_req_data(
1589 req, struct rpc_api_pipe_state);
1590 NTSTATUS status;
1592 if (tevent_req_is_nterror(req, &status)) {
1593 return status;
1596 *reply_pdu = state->incoming_pdu;
1597 reply_pdu->mem_ctx = mem_ctx;
1600 * Prevent state->incoming_pdu from being freed in
1601 * rpc_api_pipe_state_destructor()
1603 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1605 return NT_STATUS_OK;
1608 /*******************************************************************
1609 Creates krb5 auth bind.
1610 ********************************************************************/
1612 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1613 enum dcerpc_AuthLevel auth_level,
1614 RPC_HDR_AUTH *pauth_out,
1615 prs_struct *auth_data)
1617 #ifdef HAVE_KRB5
1618 int ret;
1619 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1620 DATA_BLOB tkt = data_blob_null;
1621 DATA_BLOB tkt_wrapped = data_blob_null;
1623 /* We may change the pad length before marshalling. */
1624 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
1626 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1627 a->service_principal ));
1629 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1631 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1632 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1634 if (ret) {
1635 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1636 "failed with %s\n",
1637 a->service_principal,
1638 error_message(ret) ));
1640 data_blob_free(&tkt);
1641 prs_mem_free(auth_data);
1642 return NT_STATUS_INVALID_PARAMETER;
1645 /* wrap that up in a nice GSS-API wrapping */
1646 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1648 data_blob_free(&tkt);
1650 /* Auth len in the rpc header doesn't include auth_header. */
1651 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1652 data_blob_free(&tkt_wrapped);
1653 prs_mem_free(auth_data);
1654 return NT_STATUS_NO_MEMORY;
1657 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1658 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1660 data_blob_free(&tkt_wrapped);
1661 return NT_STATUS_OK;
1662 #else
1663 return NT_STATUS_INVALID_PARAMETER;
1664 #endif
1667 /*******************************************************************
1668 Creates SPNEGO NTLMSSP auth bind.
1669 ********************************************************************/
1671 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1672 enum dcerpc_AuthLevel auth_level,
1673 RPC_HDR_AUTH *pauth_out,
1674 prs_struct *auth_data)
1676 NTSTATUS nt_status;
1677 DATA_BLOB null_blob = data_blob_null;
1678 DATA_BLOB request = data_blob_null;
1679 DATA_BLOB spnego_msg = data_blob_null;
1681 /* We may change the pad length before marshalling. */
1682 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
1684 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1685 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1686 null_blob,
1687 &request);
1689 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1690 data_blob_free(&request);
1691 prs_mem_free(auth_data);
1692 return nt_status;
1695 /* Wrap this in SPNEGO. */
1696 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1698 data_blob_free(&request);
1700 /* Auth len in the rpc header doesn't include auth_header. */
1701 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1702 data_blob_free(&spnego_msg);
1703 prs_mem_free(auth_data);
1704 return NT_STATUS_NO_MEMORY;
1707 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1708 dump_data(5, spnego_msg.data, spnego_msg.length);
1710 data_blob_free(&spnego_msg);
1711 return NT_STATUS_OK;
1714 /*******************************************************************
1715 Creates NTLMSSP auth bind.
1716 ********************************************************************/
1718 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1719 enum dcerpc_AuthLevel auth_level,
1720 RPC_HDR_AUTH *pauth_out,
1721 prs_struct *auth_data)
1723 NTSTATUS nt_status;
1724 DATA_BLOB null_blob = data_blob_null;
1725 DATA_BLOB request = data_blob_null;
1727 /* We may change the pad length before marshalling. */
1728 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
1730 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1731 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1732 null_blob,
1733 &request);
1735 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1736 data_blob_free(&request);
1737 prs_mem_free(auth_data);
1738 return nt_status;
1741 /* Auth len in the rpc header doesn't include auth_header. */
1742 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1743 data_blob_free(&request);
1744 prs_mem_free(auth_data);
1745 return NT_STATUS_NO_MEMORY;
1748 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1749 dump_data(5, request.data, request.length);
1751 data_blob_free(&request);
1752 return NT_STATUS_OK;
1755 /*******************************************************************
1756 Creates schannel auth bind.
1757 ********************************************************************/
1759 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1760 enum dcerpc_AuthLevel auth_level,
1761 RPC_HDR_AUTH *pauth_out,
1762 prs_struct *auth_data)
1764 struct NL_AUTH_MESSAGE r;
1765 enum ndr_err_code ndr_err;
1766 DATA_BLOB blob;
1768 /* We may change the pad length before marshalling. */
1769 init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
1771 /* Use lp_workgroup() if domain not specified */
1773 if (!cli->auth->domain || !cli->auth->domain[0]) {
1774 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1775 if (cli->auth->domain == NULL) {
1776 return NT_STATUS_NO_MEMORY;
1781 * Now marshall the data into the auth parse_struct.
1784 r.MessageType = NL_NEGOTIATE_REQUEST;
1785 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1786 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1787 r.oem_netbios_domain.a = cli->auth->domain;
1788 r.oem_netbios_computer.a = global_myname();
1790 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &r,
1791 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
1792 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1793 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1794 prs_mem_free(auth_data);
1795 return ndr_map_error2ntstatus(ndr_err);
1798 if (DEBUGLEVEL >= 10) {
1799 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
1802 if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
1804 prs_mem_free(auth_data);
1805 return NT_STATUS_NO_MEMORY;
1808 return NT_STATUS_OK;
1811 /*******************************************************************
1812 Creates the internals of a DCE/RPC bind request or alter context PDU.
1813 ********************************************************************/
1815 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type,
1816 prs_struct *rpc_out,
1817 uint32 rpc_call_id,
1818 const struct ndr_syntax_id *abstract,
1819 const struct ndr_syntax_id *transfer,
1820 RPC_HDR_AUTH *phdr_auth,
1821 prs_struct *pauth_info)
1823 RPC_HDR hdr;
1824 RPC_HDR_RB hdr_rb;
1825 RPC_CONTEXT rpc_ctx;
1826 uint16 auth_len = prs_offset(pauth_info);
1827 uint8 ss_padding_len = 0;
1828 uint16 frag_len = 0;
1830 /* create the RPC context. */
1831 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1833 /* create the bind request RPC_HDR_RB */
1834 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1836 /* Start building the frag length. */
1837 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1839 /* Do we need to pad ? */
1840 if (auth_len) {
1841 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1842 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1843 ss_padding_len = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1844 phdr_auth->auth_pad_len = ss_padding_len;
1846 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1849 /* Create the request RPC_HDR */
1850 init_rpc_hdr(&hdr, pkt_type, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id, frag_len, auth_len);
1852 /* Marshall the RPC header */
1853 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1854 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1855 return NT_STATUS_NO_MEMORY;
1858 /* Marshall the bind request data */
1859 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1860 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1861 return NT_STATUS_NO_MEMORY;
1865 * Grow the outgoing buffer to store any auth info.
1868 if(auth_len != 0) {
1869 if (ss_padding_len) {
1870 char pad[CLIENT_NDR_PADDING_SIZE];
1871 memset(pad, '\0', CLIENT_NDR_PADDING_SIZE);
1872 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1873 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1874 return NT_STATUS_NO_MEMORY;
1878 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1879 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1880 return NT_STATUS_NO_MEMORY;
1884 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1885 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1886 return NT_STATUS_NO_MEMORY;
1890 return NT_STATUS_OK;
1893 /*******************************************************************
1894 Creates a DCE/RPC bind request.
1895 ********************************************************************/
1897 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1898 prs_struct *rpc_out,
1899 uint32 rpc_call_id,
1900 const struct ndr_syntax_id *abstract,
1901 const struct ndr_syntax_id *transfer,
1902 enum pipe_auth_type auth_type,
1903 enum dcerpc_AuthLevel auth_level)
1905 RPC_HDR_AUTH hdr_auth;
1906 prs_struct auth_info;
1907 NTSTATUS ret = NT_STATUS_OK;
1909 ZERO_STRUCT(hdr_auth);
1910 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1911 return NT_STATUS_NO_MEMORY;
1913 switch (auth_type) {
1914 case PIPE_AUTH_TYPE_SCHANNEL:
1915 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1916 if (!NT_STATUS_IS_OK(ret)) {
1917 prs_mem_free(&auth_info);
1918 return ret;
1920 break;
1922 case PIPE_AUTH_TYPE_NTLMSSP:
1923 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1924 if (!NT_STATUS_IS_OK(ret)) {
1925 prs_mem_free(&auth_info);
1926 return ret;
1928 break;
1930 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1931 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1932 if (!NT_STATUS_IS_OK(ret)) {
1933 prs_mem_free(&auth_info);
1934 return ret;
1936 break;
1938 case PIPE_AUTH_TYPE_KRB5:
1939 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1940 if (!NT_STATUS_IS_OK(ret)) {
1941 prs_mem_free(&auth_info);
1942 return ret;
1944 break;
1946 case PIPE_AUTH_TYPE_NONE:
1947 break;
1949 default:
1950 /* "Can't" happen. */
1951 return NT_STATUS_INVALID_INFO_CLASS;
1954 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1955 rpc_out,
1956 rpc_call_id,
1957 abstract,
1958 transfer,
1959 &hdr_auth,
1960 &auth_info);
1962 prs_mem_free(&auth_info);
1963 return ret;
1966 /*******************************************************************
1967 Create and add the NTLMSSP sign/seal auth header and data.
1968 ********************************************************************/
1970 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1971 RPC_HDR *phdr,
1972 uint32 ss_padding_len,
1973 prs_struct *outgoing_pdu)
1975 RPC_HDR_AUTH auth_info;
1976 NTSTATUS status;
1977 DATA_BLOB auth_blob = data_blob_null;
1978 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1979 TALLOC_CTX *frame;
1981 if (!cli->auth->a_u.ntlmssp_state) {
1982 return NT_STATUS_INVALID_PARAMETER;
1985 frame = talloc_stackframe();
1987 /* Init and marshall the auth header. */
1988 init_rpc_hdr_auth(&auth_info,
1989 map_pipe_auth_type_to_rpc_auth_type(
1990 cli->auth->auth_type),
1991 cli->auth->auth_level,
1992 ss_padding_len,
1993 1 /* context id. */);
1995 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1996 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1997 talloc_free(frame);
1998 return NT_STATUS_NO_MEMORY;
2001 switch (cli->auth->auth_level) {
2002 case DCERPC_AUTH_LEVEL_PRIVACY:
2003 /* Data portion is encrypted. */
2004 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
2005 frame,
2006 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
2007 data_and_pad_len,
2008 (unsigned char *)prs_data_p(outgoing_pdu),
2009 (size_t)prs_offset(outgoing_pdu),
2010 &auth_blob);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 talloc_free(frame);
2013 return status;
2015 break;
2017 case DCERPC_AUTH_LEVEL_INTEGRITY:
2018 /* Data is signed. */
2019 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
2020 frame,
2021 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
2022 data_and_pad_len,
2023 (unsigned char *)prs_data_p(outgoing_pdu),
2024 (size_t)prs_offset(outgoing_pdu),
2025 &auth_blob);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 talloc_free(frame);
2028 return status;
2030 break;
2032 default:
2033 /* Can't happen. */
2034 smb_panic("bad auth level");
2035 /* Notreached. */
2036 return NT_STATUS_INVALID_PARAMETER;
2039 /* Finally marshall the blob. */
2041 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
2042 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
2043 (unsigned int)NTLMSSP_SIG_SIZE));
2044 talloc_free(frame);
2045 return NT_STATUS_NO_MEMORY;
2048 talloc_free(frame);
2049 return NT_STATUS_OK;
2052 /*******************************************************************
2053 Create and add the schannel sign/seal auth header and data.
2054 ********************************************************************/
2056 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2057 RPC_HDR *phdr,
2058 uint32 ss_padding_len,
2059 prs_struct *outgoing_pdu)
2061 RPC_HDR_AUTH auth_info;
2062 struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2063 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2064 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2065 DATA_BLOB blob;
2066 NTSTATUS status;
2068 if (!sas) {
2069 return NT_STATUS_INVALID_PARAMETER;
2072 /* Init and marshall the auth header. */
2073 init_rpc_hdr_auth(&auth_info,
2074 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2075 cli->auth->auth_level,
2076 ss_padding_len,
2077 1 /* context id. */);
2079 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
2080 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
2081 return NT_STATUS_NO_MEMORY;
2084 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2085 sas->seq_num));
2087 switch (cli->auth->auth_level) {
2088 case DCERPC_AUTH_LEVEL_PRIVACY:
2089 status = netsec_outgoing_packet(sas,
2090 talloc_tos(),
2091 true,
2092 (uint8_t *)data_p,
2093 data_and_pad_len,
2094 &blob);
2095 break;
2096 case DCERPC_AUTH_LEVEL_INTEGRITY:
2097 status = netsec_outgoing_packet(sas,
2098 talloc_tos(),
2099 false,
2100 (uint8_t *)data_p,
2101 data_and_pad_len,
2102 &blob);
2103 break;
2104 default:
2105 status = NT_STATUS_INTERNAL_ERROR;
2106 break;
2109 if (!NT_STATUS_IS_OK(status)) {
2110 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2111 nt_errstr(status)));
2112 return status;
2115 if (DEBUGLEVEL >= 10) {
2116 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2119 /* Finally marshall the blob. */
2120 if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
2121 return NT_STATUS_NO_MEMORY;
2124 return NT_STATUS_OK;
2127 /*******************************************************************
2128 Calculate how much data we're going to send in this packet, also
2129 work out any sign/seal padding length.
2130 ********************************************************************/
2132 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2133 uint32 data_left,
2134 uint16 *p_frag_len,
2135 uint16 *p_auth_len,
2136 uint32 *p_ss_padding)
2138 uint32 data_space, data_len;
2140 #if 0
2141 if ((data_left > 0) && (sys_random() % 2)) {
2142 data_left = MAX(data_left/2, 1);
2144 #endif
2146 switch (cli->auth->auth_level) {
2147 case DCERPC_AUTH_LEVEL_NONE:
2148 case DCERPC_AUTH_LEVEL_CONNECT:
2149 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2150 data_len = MIN(data_space, data_left);
2151 *p_ss_padding = 0;
2152 *p_auth_len = 0;
2153 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2154 return data_len;
2156 case DCERPC_AUTH_LEVEL_INTEGRITY:
2157 case DCERPC_AUTH_LEVEL_PRIVACY:
2158 /* Treat the same for all authenticated rpc requests. */
2159 switch(cli->auth->auth_type) {
2160 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2161 case PIPE_AUTH_TYPE_NTLMSSP:
2162 *p_auth_len = NTLMSSP_SIG_SIZE;
2163 break;
2164 case PIPE_AUTH_TYPE_SCHANNEL:
2165 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2166 break;
2167 default:
2168 smb_panic("bad auth type");
2169 break;
2172 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2173 RPC_HDR_AUTH_LEN - *p_auth_len;
2175 data_len = MIN(data_space, data_left);
2176 *p_ss_padding = 0;
2177 if (data_len % CLIENT_NDR_PADDING_SIZE) {
2178 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2180 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
2181 data_len + *p_ss_padding + /* data plus padding. */
2182 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
2183 return data_len;
2185 default:
2186 smb_panic("bad auth level");
2187 /* Notreached. */
2188 return 0;
2192 /*******************************************************************
2193 External interface.
2194 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2195 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2196 and deals with signing/sealing details.
2197 ********************************************************************/
2199 struct rpc_api_pipe_req_state {
2200 struct event_context *ev;
2201 struct rpc_pipe_client *cli;
2202 uint8_t op_num;
2203 uint32_t call_id;
2204 prs_struct *req_data;
2205 uint32_t req_data_sent;
2206 prs_struct outgoing_frag;
2207 prs_struct reply_pdu;
2210 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2212 prs_mem_free(&s->outgoing_frag);
2213 prs_mem_free(&s->reply_pdu);
2214 return 0;
2217 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2218 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2219 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2220 bool *is_last_frag);
2222 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2223 struct event_context *ev,
2224 struct rpc_pipe_client *cli,
2225 uint8_t op_num,
2226 prs_struct *req_data)
2228 struct tevent_req *req, *subreq;
2229 struct rpc_api_pipe_req_state *state;
2230 NTSTATUS status;
2231 bool is_last_frag;
2233 req = tevent_req_create(mem_ctx, &state,
2234 struct rpc_api_pipe_req_state);
2235 if (req == NULL) {
2236 return NULL;
2238 state->ev = ev;
2239 state->cli = cli;
2240 state->op_num = op_num;
2241 state->req_data = req_data;
2242 state->req_data_sent = 0;
2243 state->call_id = get_rpc_call_id();
2245 if (cli->max_xmit_frag
2246 < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2247 /* Server is screwed up ! */
2248 status = NT_STATUS_INVALID_PARAMETER;
2249 goto post_status;
2252 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2254 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2255 state, MARSHALL)) {
2256 goto fail;
2259 talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2261 status = prepare_next_frag(state, &is_last_frag);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 goto post_status;
2266 if (is_last_frag) {
2267 subreq = rpc_api_pipe_send(state, ev, state->cli,
2268 &state->outgoing_frag,
2269 DCERPC_PKT_RESPONSE);
2270 if (subreq == NULL) {
2271 goto fail;
2273 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2274 } else {
2275 subreq = rpc_write_send(
2276 state, ev, cli->transport,
2277 (uint8_t *)prs_data_p(&state->outgoing_frag),
2278 prs_offset(&state->outgoing_frag));
2279 if (subreq == NULL) {
2280 goto fail;
2282 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2283 req);
2285 return req;
2287 post_status:
2288 tevent_req_nterror(req, status);
2289 return tevent_req_post(req, ev);
2290 fail:
2291 TALLOC_FREE(req);
2292 return NULL;
2295 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2296 bool *is_last_frag)
2298 RPC_HDR hdr;
2299 RPC_HDR_REQ hdr_req;
2300 uint32_t data_sent_thistime;
2301 uint16_t auth_len;
2302 uint16_t frag_len;
2303 uint8_t flags = 0;
2304 uint32_t ss_padding;
2305 uint32_t data_left;
2306 char pad[8] = { 0, };
2307 NTSTATUS status;
2309 data_left = prs_offset(state->req_data) - state->req_data_sent;
2311 data_sent_thistime = calculate_data_len_tosend(
2312 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2314 if (state->req_data_sent == 0) {
2315 flags = DCERPC_PFC_FLAG_FIRST;
2318 if (data_sent_thistime == data_left) {
2319 flags |= DCERPC_PFC_FLAG_LAST;
2322 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2323 return NT_STATUS_NO_MEMORY;
2326 /* Create and marshall the header and request header. */
2327 init_rpc_hdr(&hdr, DCERPC_PKT_REQUEST, flags, state->call_id, frag_len,
2328 auth_len);
2330 if (!smb_io_rpc_hdr("hdr ", &hdr, &state->outgoing_frag, 0)) {
2331 return NT_STATUS_NO_MEMORY;
2334 /* Create the rpc request RPC_HDR_REQ */
2335 init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2336 state->op_num);
2338 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2339 &state->outgoing_frag, 0)) {
2340 return NT_STATUS_NO_MEMORY;
2343 /* Copy in the data, plus any ss padding. */
2344 if (!prs_append_some_prs_data(&state->outgoing_frag,
2345 state->req_data, state->req_data_sent,
2346 data_sent_thistime)) {
2347 return NT_STATUS_NO_MEMORY;
2350 /* Copy the sign/seal padding data. */
2351 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2352 return NT_STATUS_NO_MEMORY;
2355 /* Generate any auth sign/seal and add the auth footer. */
2356 switch (state->cli->auth->auth_type) {
2357 case PIPE_AUTH_TYPE_NONE:
2358 status = NT_STATUS_OK;
2359 break;
2360 case PIPE_AUTH_TYPE_NTLMSSP:
2361 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2362 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2363 &state->outgoing_frag);
2364 break;
2365 case PIPE_AUTH_TYPE_SCHANNEL:
2366 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2367 &state->outgoing_frag);
2368 break;
2369 default:
2370 status = NT_STATUS_INVALID_PARAMETER;
2371 break;
2374 state->req_data_sent += data_sent_thistime;
2375 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2377 return status;
2380 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2382 struct tevent_req *req = tevent_req_callback_data(
2383 subreq, struct tevent_req);
2384 struct rpc_api_pipe_req_state *state = tevent_req_data(
2385 req, struct rpc_api_pipe_req_state);
2386 NTSTATUS status;
2387 bool is_last_frag;
2389 status = rpc_write_recv(subreq);
2390 TALLOC_FREE(subreq);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 tevent_req_nterror(req, status);
2393 return;
2396 status = prepare_next_frag(state, &is_last_frag);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 tevent_req_nterror(req, status);
2399 return;
2402 if (is_last_frag) {
2403 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2404 &state->outgoing_frag,
2405 DCERPC_PKT_RESPONSE);
2406 if (tevent_req_nomem(subreq, req)) {
2407 return;
2409 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2410 } else {
2411 subreq = rpc_write_send(
2412 state, state->ev,
2413 state->cli->transport,
2414 (uint8_t *)prs_data_p(&state->outgoing_frag),
2415 prs_offset(&state->outgoing_frag));
2416 if (tevent_req_nomem(subreq, req)) {
2417 return;
2419 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2420 req);
2424 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2426 struct tevent_req *req = tevent_req_callback_data(
2427 subreq, struct tevent_req);
2428 struct rpc_api_pipe_req_state *state = tevent_req_data(
2429 req, struct rpc_api_pipe_req_state);
2430 NTSTATUS status;
2432 status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2433 TALLOC_FREE(subreq);
2434 if (!NT_STATUS_IS_OK(status)) {
2435 tevent_req_nterror(req, status);
2436 return;
2438 tevent_req_done(req);
2441 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2442 prs_struct *reply_pdu)
2444 struct rpc_api_pipe_req_state *state = tevent_req_data(
2445 req, struct rpc_api_pipe_req_state);
2446 NTSTATUS status;
2448 if (tevent_req_is_nterror(req, &status)) {
2450 * We always have to initialize to reply pdu, even if there is
2451 * none. The rpccli_* caller routines expect this.
2453 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2454 return status;
2457 *reply_pdu = state->reply_pdu;
2458 reply_pdu->mem_ctx = mem_ctx;
2461 * Prevent state->req_pdu from being freed in
2462 * rpc_api_pipe_req_state_destructor()
2464 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2466 return NT_STATUS_OK;
2469 #if 0
2470 /****************************************************************************
2471 Set the handle state.
2472 ****************************************************************************/
2474 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2475 const char *pipe_name, uint16 device_state)
2477 bool state_set = False;
2478 char param[2];
2479 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2480 char *rparam = NULL;
2481 char *rdata = NULL;
2482 uint32 rparam_len, rdata_len;
2484 if (pipe_name == NULL)
2485 return False;
2487 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2488 cli->fnum, pipe_name, device_state));
2490 /* create parameters: device state */
2491 SSVAL(param, 0, device_state);
2493 /* create setup parameters. */
2494 setup[0] = 0x0001;
2495 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2497 /* send the data on \PIPE\ */
2498 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2499 setup, 2, 0, /* setup, length, max */
2500 param, 2, 0, /* param, length, max */
2501 NULL, 0, 1024, /* data, length, max */
2502 &rparam, &rparam_len, /* return param, length */
2503 &rdata, &rdata_len)) /* return data, length */
2505 DEBUG(5, ("Set Handle state: return OK\n"));
2506 state_set = True;
2509 SAFE_FREE(rparam);
2510 SAFE_FREE(rdata);
2512 return state_set;
2514 #endif
2516 /****************************************************************************
2517 Check the rpc bind acknowledge response.
2518 ****************************************************************************/
2520 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2521 const struct ndr_syntax_id *transfer)
2523 if ( hdr_ba->addr.len == 0) {
2524 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2527 /* check the transfer syntax */
2528 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2529 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2530 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2531 return False;
2534 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2535 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2536 hdr_ba->res.num_results, hdr_ba->res.reason));
2539 DEBUG(5,("check_bind_response: accepted!\n"));
2540 return True;
2543 /*******************************************************************
2544 Creates a DCE/RPC bind authentication response.
2545 This is the packet that is sent back to the server once we
2546 have received a BIND-ACK, to finish the third leg of
2547 the authentication handshake.
2548 ********************************************************************/
2550 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2551 uint32 rpc_call_id,
2552 enum pipe_auth_type auth_type,
2553 enum dcerpc_AuthLevel auth_level,
2554 DATA_BLOB *pauth_blob,
2555 prs_struct *rpc_out)
2557 RPC_HDR hdr;
2558 RPC_HDR_AUTH hdr_auth;
2559 uint32 pad = 0;
2561 /* Create the request RPC_HDR */
2562 init_rpc_hdr(&hdr, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id,
2563 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2564 pauth_blob->length );
2566 /* Marshall it. */
2567 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2568 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2569 return NT_STATUS_NO_MEMORY;
2573 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2574 about padding - shouldn't this pad to length CLIENT_NDR_PADDING_SIZE ? JRA.
2577 /* 4 bytes padding. */
2578 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2579 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2580 return NT_STATUS_NO_MEMORY;
2583 /* Create the request RPC_HDR_AUTHA */
2584 init_rpc_hdr_auth(&hdr_auth,
2585 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2586 auth_level, 0, 1);
2588 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2589 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2590 return NT_STATUS_NO_MEMORY;
2594 * Append the auth data to the outgoing buffer.
2597 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2598 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2599 return NT_STATUS_NO_MEMORY;
2602 return NT_STATUS_OK;
2605 /*******************************************************************
2606 Creates a DCE/RPC bind alter context authentication request which
2607 may contain a spnego auth blobl
2608 ********************************************************************/
2610 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2611 const struct ndr_syntax_id *abstract,
2612 const struct ndr_syntax_id *transfer,
2613 enum dcerpc_AuthLevel auth_level,
2614 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2615 prs_struct *rpc_out)
2617 RPC_HDR_AUTH hdr_auth;
2618 prs_struct auth_info;
2619 NTSTATUS ret = NT_STATUS_OK;
2621 ZERO_STRUCT(hdr_auth);
2622 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2623 return NT_STATUS_NO_MEMORY;
2625 /* We may change the pad length before marshalling. */
2626 init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
2628 if (pauth_blob->length) {
2629 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2630 prs_mem_free(&auth_info);
2631 return NT_STATUS_NO_MEMORY;
2635 ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2636 rpc_out,
2637 rpc_call_id,
2638 abstract,
2639 transfer,
2640 &hdr_auth,
2641 &auth_info);
2642 prs_mem_free(&auth_info);
2643 return ret;
2646 /****************************************************************************
2647 Do an rpc bind.
2648 ****************************************************************************/
2650 struct rpc_pipe_bind_state {
2651 struct event_context *ev;
2652 struct rpc_pipe_client *cli;
2653 prs_struct rpc_out;
2654 uint32_t rpc_call_id;
2657 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2659 prs_mem_free(&state->rpc_out);
2660 return 0;
2663 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2664 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2665 struct rpc_pipe_bind_state *state,
2666 struct rpc_hdr_info *phdr,
2667 prs_struct *reply_pdu);
2668 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2669 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2670 struct rpc_pipe_bind_state *state,
2671 struct rpc_hdr_info *phdr,
2672 prs_struct *reply_pdu);
2673 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2675 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2676 struct event_context *ev,
2677 struct rpc_pipe_client *cli,
2678 struct cli_pipe_auth_data *auth)
2680 struct tevent_req *req, *subreq;
2681 struct rpc_pipe_bind_state *state;
2682 NTSTATUS status;
2684 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2685 if (req == NULL) {
2686 return NULL;
2689 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2690 rpccli_pipe_txt(talloc_tos(), cli),
2691 (unsigned int)auth->auth_type,
2692 (unsigned int)auth->auth_level ));
2694 state->ev = ev;
2695 state->cli = cli;
2696 state->rpc_call_id = get_rpc_call_id();
2698 prs_init_empty(&state->rpc_out, state, MARSHALL);
2699 talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2701 cli->auth = talloc_move(cli, &auth);
2703 /* Marshall the outgoing data. */
2704 status = create_rpc_bind_req(cli, &state->rpc_out,
2705 state->rpc_call_id,
2706 &cli->abstract_syntax,
2707 &cli->transfer_syntax,
2708 cli->auth->auth_type,
2709 cli->auth->auth_level);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 goto post_status;
2715 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2716 DCERPC_PKT_BIND_ACK);
2717 if (subreq == NULL) {
2718 goto fail;
2720 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2721 return req;
2723 post_status:
2724 tevent_req_nterror(req, status);
2725 return tevent_req_post(req, ev);
2726 fail:
2727 TALLOC_FREE(req);
2728 return NULL;
2731 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2733 struct tevent_req *req = tevent_req_callback_data(
2734 subreq, struct tevent_req);
2735 struct rpc_pipe_bind_state *state = tevent_req_data(
2736 req, struct rpc_pipe_bind_state);
2737 prs_struct reply_pdu;
2738 struct rpc_hdr_info hdr;
2739 struct rpc_hdr_ba_info hdr_ba;
2740 NTSTATUS status;
2742 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2743 TALLOC_FREE(subreq);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2746 rpccli_pipe_txt(talloc_tos(), state->cli),
2747 nt_errstr(status)));
2748 tevent_req_nterror(req, status);
2749 return;
2752 /* Unmarshall the RPC header */
2753 if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2754 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2755 prs_mem_free(&reply_pdu);
2756 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2757 return;
2760 if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2761 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2762 "RPC_HDR_BA.\n"));
2763 prs_mem_free(&reply_pdu);
2764 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2765 return;
2768 if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2769 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2770 prs_mem_free(&reply_pdu);
2771 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2772 return;
2775 state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2776 state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2779 * For authenticated binds we may need to do 3 or 4 leg binds.
2782 switch(state->cli->auth->auth_type) {
2784 case PIPE_AUTH_TYPE_NONE:
2785 case PIPE_AUTH_TYPE_SCHANNEL:
2786 /* Bind complete. */
2787 prs_mem_free(&reply_pdu);
2788 tevent_req_done(req);
2789 break;
2791 case PIPE_AUTH_TYPE_NTLMSSP:
2792 /* Need to send AUTH3 packet - no reply. */
2793 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2794 &reply_pdu);
2795 prs_mem_free(&reply_pdu);
2796 if (!NT_STATUS_IS_OK(status)) {
2797 tevent_req_nterror(req, status);
2799 break;
2801 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2802 /* Need to send alter context request and reply. */
2803 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2804 &reply_pdu);
2805 prs_mem_free(&reply_pdu);
2806 if (!NT_STATUS_IS_OK(status)) {
2807 tevent_req_nterror(req, status);
2809 break;
2811 case PIPE_AUTH_TYPE_KRB5:
2812 /* */
2814 default:
2815 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2816 (unsigned int)state->cli->auth->auth_type));
2817 prs_mem_free(&reply_pdu);
2818 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2822 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2823 struct rpc_pipe_bind_state *state,
2824 struct rpc_hdr_info *phdr,
2825 prs_struct *reply_pdu)
2827 DATA_BLOB server_response = data_blob_null;
2828 DATA_BLOB client_reply = data_blob_null;
2829 struct rpc_hdr_auth_info hdr_auth;
2830 struct tevent_req *subreq;
2831 NTSTATUS status;
2833 if ((phdr->auth_len == 0)
2834 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2835 return NT_STATUS_INVALID_PARAMETER;
2838 if (!prs_set_offset(
2839 reply_pdu,
2840 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2841 return NT_STATUS_INVALID_PARAMETER;
2844 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2845 return NT_STATUS_INVALID_PARAMETER;
2848 /* TODO - check auth_type/auth_level match. */
2850 server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2851 prs_copy_data_out((char *)server_response.data, reply_pdu,
2852 phdr->auth_len);
2854 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2855 server_response, &client_reply);
2857 if (!NT_STATUS_IS_OK(status)) {
2858 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2859 "blob failed: %s.\n", nt_errstr(status)));
2860 return status;
2863 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2865 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2866 state->cli->auth->auth_type,
2867 state->cli->auth->auth_level,
2868 &client_reply, &state->rpc_out);
2869 data_blob_free(&client_reply);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 return status;
2875 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2876 (uint8_t *)prs_data_p(&state->rpc_out),
2877 prs_offset(&state->rpc_out));
2878 if (subreq == NULL) {
2879 return NT_STATUS_NO_MEMORY;
2881 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2882 return NT_STATUS_OK;
2885 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2887 struct tevent_req *req = tevent_req_callback_data(
2888 subreq, struct tevent_req);
2889 NTSTATUS status;
2891 status = rpc_write_recv(subreq);
2892 TALLOC_FREE(subreq);
2893 if (!NT_STATUS_IS_OK(status)) {
2894 tevent_req_nterror(req, status);
2895 return;
2897 tevent_req_done(req);
2900 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2901 struct rpc_pipe_bind_state *state,
2902 struct rpc_hdr_info *phdr,
2903 prs_struct *reply_pdu)
2905 DATA_BLOB server_spnego_response = data_blob_null;
2906 DATA_BLOB server_ntlm_response = data_blob_null;
2907 DATA_BLOB client_reply = data_blob_null;
2908 DATA_BLOB tmp_blob = data_blob_null;
2909 RPC_HDR_AUTH hdr_auth;
2910 struct tevent_req *subreq;
2911 NTSTATUS status;
2913 if ((phdr->auth_len == 0)
2914 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2915 return NT_STATUS_INVALID_PARAMETER;
2918 /* Process the returned NTLMSSP blob first. */
2919 if (!prs_set_offset(
2920 reply_pdu,
2921 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2922 return NT_STATUS_INVALID_PARAMETER;
2925 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2926 return NT_STATUS_INVALID_PARAMETER;
2929 server_spnego_response = data_blob(NULL, phdr->auth_len);
2930 prs_copy_data_out((char *)server_spnego_response.data,
2931 reply_pdu, phdr->auth_len);
2934 * The server might give us back two challenges - tmp_blob is for the
2935 * second.
2937 if (!spnego_parse_challenge(server_spnego_response,
2938 &server_ntlm_response, &tmp_blob)) {
2939 data_blob_free(&server_spnego_response);
2940 data_blob_free(&server_ntlm_response);
2941 data_blob_free(&tmp_blob);
2942 return NT_STATUS_INVALID_PARAMETER;
2945 /* We're finished with the server spnego response and the tmp_blob. */
2946 data_blob_free(&server_spnego_response);
2947 data_blob_free(&tmp_blob);
2949 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2950 server_ntlm_response, &client_reply);
2952 /* Finished with the server_ntlm response */
2953 data_blob_free(&server_ntlm_response);
2955 if (!NT_STATUS_IS_OK(status)) {
2956 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2957 "using server blob failed.\n"));
2958 data_blob_free(&client_reply);
2959 return status;
2962 /* SPNEGO wrap the client reply. */
2963 tmp_blob = spnego_gen_auth(client_reply);
2964 data_blob_free(&client_reply);
2965 client_reply = tmp_blob;
2966 tmp_blob = data_blob_null;
2968 /* Now prepare the alter context pdu. */
2969 prs_init_empty(&state->rpc_out, state, MARSHALL);
2971 status = create_rpc_alter_context(state->rpc_call_id,
2972 &state->cli->abstract_syntax,
2973 &state->cli->transfer_syntax,
2974 state->cli->auth->auth_level,
2975 &client_reply,
2976 &state->rpc_out);
2977 data_blob_free(&client_reply);
2979 if (!NT_STATUS_IS_OK(status)) {
2980 return status;
2983 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2984 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2985 if (subreq == NULL) {
2986 return NT_STATUS_NO_MEMORY;
2988 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2989 return NT_STATUS_OK;
2992 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2994 struct tevent_req *req = tevent_req_callback_data(
2995 subreq, struct tevent_req);
2996 struct rpc_pipe_bind_state *state = tevent_req_data(
2997 req, struct rpc_pipe_bind_state);
2998 DATA_BLOB server_spnego_response = data_blob_null;
2999 DATA_BLOB tmp_blob = data_blob_null;
3000 prs_struct reply_pdu;
3001 struct rpc_hdr_info hdr;
3002 struct rpc_hdr_auth_info hdr_auth;
3003 NTSTATUS status;
3005 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
3006 TALLOC_FREE(subreq);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 tevent_req_nterror(req, status);
3009 return;
3012 /* Get the auth blob from the reply. */
3013 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) {
3014 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
3015 "unmarshall RPC_HDR.\n"));
3016 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3017 return;
3020 if (!prs_set_offset(
3021 &reply_pdu,
3022 hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
3023 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3024 return;
3027 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
3028 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3029 return;
3032 server_spnego_response = data_blob(NULL, hdr.auth_len);
3033 prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
3034 hdr.auth_len);
3036 /* Check we got a valid auth response. */
3037 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
3038 OID_NTLMSSP, &tmp_blob)) {
3039 data_blob_free(&server_spnego_response);
3040 data_blob_free(&tmp_blob);
3041 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3042 return;
3045 data_blob_free(&server_spnego_response);
3046 data_blob_free(&tmp_blob);
3048 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
3049 "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
3050 tevent_req_done(req);
3053 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3055 return tevent_req_simple_recv_ntstatus(req);
3058 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3059 struct cli_pipe_auth_data *auth)
3061 TALLOC_CTX *frame = talloc_stackframe();
3062 struct event_context *ev;
3063 struct tevent_req *req;
3064 NTSTATUS status = NT_STATUS_OK;
3066 ev = event_context_init(frame);
3067 if (ev == NULL) {
3068 status = NT_STATUS_NO_MEMORY;
3069 goto fail;
3072 req = rpc_pipe_bind_send(frame, ev, cli, auth);
3073 if (req == NULL) {
3074 status = NT_STATUS_NO_MEMORY;
3075 goto fail;
3078 if (!tevent_req_poll(req, ev)) {
3079 status = map_nt_error_from_unix(errno);
3080 goto fail;
3083 status = rpc_pipe_bind_recv(req);
3084 fail:
3085 TALLOC_FREE(frame);
3086 return status;
3089 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
3091 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3092 unsigned int timeout)
3094 unsigned int old;
3096 if (rpc_cli->transport == NULL) {
3097 return RPCCLI_DEFAULT_TIMEOUT;
3100 if (rpc_cli->transport->set_timeout == NULL) {
3101 return RPCCLI_DEFAULT_TIMEOUT;
3104 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
3105 if (old == 0) {
3106 return RPCCLI_DEFAULT_TIMEOUT;
3109 return old;
3112 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
3114 if (rpc_cli == NULL) {
3115 return false;
3118 if (rpc_cli->transport == NULL) {
3119 return false;
3122 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
3125 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3127 struct cli_state *cli;
3129 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3130 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3131 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3132 return true;
3135 cli = rpc_pipe_np_smb_conn(rpc_cli);
3136 if (cli == NULL) {
3137 return false;
3139 E_md4hash(cli->password ? cli->password : "", nt_hash);
3140 return true;
3143 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3144 struct cli_pipe_auth_data **presult)
3146 struct cli_pipe_auth_data *result;
3148 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3149 if (result == NULL) {
3150 return NT_STATUS_NO_MEMORY;
3153 result->auth_type = PIPE_AUTH_TYPE_NONE;
3154 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3156 result->user_name = talloc_strdup(result, "");
3157 result->domain = talloc_strdup(result, "");
3158 if ((result->user_name == NULL) || (result->domain == NULL)) {
3159 TALLOC_FREE(result);
3160 return NT_STATUS_NO_MEMORY;
3163 *presult = result;
3164 return NT_STATUS_OK;
3167 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3169 ntlmssp_end(&auth->a_u.ntlmssp_state);
3170 return 0;
3173 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3174 enum pipe_auth_type auth_type,
3175 enum dcerpc_AuthLevel auth_level,
3176 const char *domain,
3177 const char *username,
3178 const char *password,
3179 struct cli_pipe_auth_data **presult)
3181 struct cli_pipe_auth_data *result;
3182 NTSTATUS status;
3184 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3185 if (result == NULL) {
3186 return NT_STATUS_NO_MEMORY;
3189 result->auth_type = auth_type;
3190 result->auth_level = auth_level;
3192 result->user_name = talloc_strdup(result, username);
3193 result->domain = talloc_strdup(result, domain);
3194 if ((result->user_name == NULL) || (result->domain == NULL)) {
3195 status = NT_STATUS_NO_MEMORY;
3196 goto fail;
3199 status = ntlmssp_client_start(NULL,
3200 global_myname(),
3201 lp_workgroup(),
3202 lp_client_ntlmv2_auth(),
3203 &result->a_u.ntlmssp_state);
3204 if (!NT_STATUS_IS_OK(status)) {
3205 goto fail;
3208 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3210 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3211 if (!NT_STATUS_IS_OK(status)) {
3212 goto fail;
3215 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3216 if (!NT_STATUS_IS_OK(status)) {
3217 goto fail;
3220 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3221 if (!NT_STATUS_IS_OK(status)) {
3222 goto fail;
3226 * Turn off sign+seal to allow selected auth level to turn it back on.
3228 result->a_u.ntlmssp_state->neg_flags &=
3229 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3231 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3232 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3233 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3234 result->a_u.ntlmssp_state->neg_flags
3235 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3238 *presult = result;
3239 return NT_STATUS_OK;
3241 fail:
3242 TALLOC_FREE(result);
3243 return status;
3246 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3247 enum dcerpc_AuthLevel auth_level,
3248 struct netlogon_creds_CredentialState *creds,
3249 struct cli_pipe_auth_data **presult)
3251 struct cli_pipe_auth_data *result;
3253 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3254 if (result == NULL) {
3255 return NT_STATUS_NO_MEMORY;
3258 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3259 result->auth_level = auth_level;
3261 result->user_name = talloc_strdup(result, "");
3262 result->domain = talloc_strdup(result, domain);
3263 if ((result->user_name == NULL) || (result->domain == NULL)) {
3264 goto fail;
3267 result->a_u.schannel_auth = talloc(result, struct schannel_state);
3268 if (result->a_u.schannel_auth == NULL) {
3269 goto fail;
3272 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3273 result->a_u.schannel_auth->seq_num = 0;
3274 result->a_u.schannel_auth->initiator = true;
3275 result->a_u.schannel_auth->creds = creds;
3277 *presult = result;
3278 return NT_STATUS_OK;
3280 fail:
3281 TALLOC_FREE(result);
3282 return NT_STATUS_NO_MEMORY;
3285 #ifdef HAVE_KRB5
3286 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3288 data_blob_free(&auth->session_key);
3289 return 0;
3291 #endif
3293 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3294 enum dcerpc_AuthLevel auth_level,
3295 const char *service_princ,
3296 const char *username,
3297 const char *password,
3298 struct cli_pipe_auth_data **presult)
3300 #ifdef HAVE_KRB5
3301 struct cli_pipe_auth_data *result;
3303 if ((username != NULL) && (password != NULL)) {
3304 int ret = kerberos_kinit_password(username, password, 0, NULL);
3305 if (ret != 0) {
3306 return NT_STATUS_ACCESS_DENIED;
3310 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3311 if (result == NULL) {
3312 return NT_STATUS_NO_MEMORY;
3315 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3316 result->auth_level = auth_level;
3319 * Username / domain need fixing!
3321 result->user_name = talloc_strdup(result, "");
3322 result->domain = talloc_strdup(result, "");
3323 if ((result->user_name == NULL) || (result->domain == NULL)) {
3324 goto fail;
3327 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3328 result, struct kerberos_auth_struct);
3329 if (result->a_u.kerberos_auth == NULL) {
3330 goto fail;
3332 talloc_set_destructor(result->a_u.kerberos_auth,
3333 cli_auth_kerberos_data_destructor);
3335 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3336 result, service_princ);
3337 if (result->a_u.kerberos_auth->service_principal == NULL) {
3338 goto fail;
3341 *presult = result;
3342 return NT_STATUS_OK;
3344 fail:
3345 TALLOC_FREE(result);
3346 return NT_STATUS_NO_MEMORY;
3347 #else
3348 return NT_STATUS_NOT_SUPPORTED;
3349 #endif
3353 * Create an rpc pipe client struct, connecting to a tcp port.
3355 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3356 uint16_t port,
3357 const struct ndr_syntax_id *abstract_syntax,
3358 struct rpc_pipe_client **presult)
3360 struct rpc_pipe_client *result;
3361 struct sockaddr_storage addr;
3362 NTSTATUS status;
3363 int fd;
3365 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3366 if (result == NULL) {
3367 return NT_STATUS_NO_MEMORY;
3370 result->abstract_syntax = *abstract_syntax;
3371 result->transfer_syntax = ndr_transfer_syntax;
3372 result->dispatch = cli_do_rpc_ndr;
3373 result->dispatch_send = cli_do_rpc_ndr_send;
3374 result->dispatch_recv = cli_do_rpc_ndr_recv;
3376 result->desthost = talloc_strdup(result, host);
3377 result->srv_name_slash = talloc_asprintf_strupper_m(
3378 result, "\\\\%s", result->desthost);
3379 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3380 status = NT_STATUS_NO_MEMORY;
3381 goto fail;
3384 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3385 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3387 if (!resolve_name(host, &addr, 0, false)) {
3388 status = NT_STATUS_NOT_FOUND;
3389 goto fail;
3392 status = open_socket_out(&addr, port, 60, &fd);
3393 if (!NT_STATUS_IS_OK(status)) {
3394 goto fail;
3396 set_socket_options(fd, lp_socket_options());
3398 status = rpc_transport_sock_init(result, fd, &result->transport);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 close(fd);
3401 goto fail;
3404 result->transport->transport = NCACN_IP_TCP;
3406 *presult = result;
3407 return NT_STATUS_OK;
3409 fail:
3410 TALLOC_FREE(result);
3411 return status;
3415 * Determine the tcp port on which a dcerpc interface is listening
3416 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3417 * target host.
3419 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3420 const struct ndr_syntax_id *abstract_syntax,
3421 uint16_t *pport)
3423 NTSTATUS status;
3424 struct rpc_pipe_client *epm_pipe = NULL;
3425 struct cli_pipe_auth_data *auth = NULL;
3426 struct dcerpc_binding *map_binding = NULL;
3427 struct dcerpc_binding *res_binding = NULL;
3428 struct epm_twr_t *map_tower = NULL;
3429 struct epm_twr_t *res_towers = NULL;
3430 struct policy_handle *entry_handle = NULL;
3431 uint32_t num_towers = 0;
3432 uint32_t max_towers = 1;
3433 struct epm_twr_p_t towers;
3434 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3436 if (pport == NULL) {
3437 status = NT_STATUS_INVALID_PARAMETER;
3438 goto done;
3441 /* open the connection to the endpoint mapper */
3442 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3443 &ndr_table_epmapper.syntax_id,
3444 &epm_pipe);
3446 if (!NT_STATUS_IS_OK(status)) {
3447 goto done;
3450 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3451 if (!NT_STATUS_IS_OK(status)) {
3452 goto done;
3455 status = rpc_pipe_bind(epm_pipe, auth);
3456 if (!NT_STATUS_IS_OK(status)) {
3457 goto done;
3460 /* create tower for asking the epmapper */
3462 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3463 if (map_binding == NULL) {
3464 status = NT_STATUS_NO_MEMORY;
3465 goto done;
3468 map_binding->transport = NCACN_IP_TCP;
3469 map_binding->object = *abstract_syntax;
3470 map_binding->host = host; /* needed? */
3471 map_binding->endpoint = "0"; /* correct? needed? */
3473 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3474 if (map_tower == NULL) {
3475 status = NT_STATUS_NO_MEMORY;
3476 goto done;
3479 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3480 &(map_tower->tower));
3481 if (!NT_STATUS_IS_OK(status)) {
3482 goto done;
3485 /* allocate further parameters for the epm_Map call */
3487 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3488 if (res_towers == NULL) {
3489 status = NT_STATUS_NO_MEMORY;
3490 goto done;
3492 towers.twr = res_towers;
3494 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3495 if (entry_handle == NULL) {
3496 status = NT_STATUS_NO_MEMORY;
3497 goto done;
3500 /* ask the endpoint mapper for the port */
3502 status = rpccli_epm_Map(epm_pipe,
3503 tmp_ctx,
3504 CONST_DISCARD(struct GUID *,
3505 &(abstract_syntax->uuid)),
3506 map_tower,
3507 entry_handle,
3508 max_towers,
3509 &num_towers,
3510 &towers);
3512 if (!NT_STATUS_IS_OK(status)) {
3513 goto done;
3516 if (num_towers != 1) {
3517 status = NT_STATUS_UNSUCCESSFUL;
3518 goto done;
3521 /* extract the port from the answer */
3523 status = dcerpc_binding_from_tower(tmp_ctx,
3524 &(towers.twr->tower),
3525 &res_binding);
3526 if (!NT_STATUS_IS_OK(status)) {
3527 goto done;
3530 /* are further checks here necessary? */
3531 if (res_binding->transport != NCACN_IP_TCP) {
3532 status = NT_STATUS_UNSUCCESSFUL;
3533 goto done;
3536 *pport = (uint16_t)atoi(res_binding->endpoint);
3538 done:
3539 TALLOC_FREE(tmp_ctx);
3540 return status;
3544 * Create a rpc pipe client struct, connecting to a host via tcp.
3545 * The port is determined by asking the endpoint mapper on the given
3546 * host.
3548 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3549 const struct ndr_syntax_id *abstract_syntax,
3550 struct rpc_pipe_client **presult)
3552 NTSTATUS status;
3553 uint16_t port = 0;
3555 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3556 if (!NT_STATUS_IS_OK(status)) {
3557 return status;
3560 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3561 abstract_syntax, presult);
3564 /********************************************************************
3565 Create a rpc pipe client struct, connecting to a unix domain socket
3566 ********************************************************************/
3567 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3568 const struct ndr_syntax_id *abstract_syntax,
3569 struct rpc_pipe_client **presult)
3571 struct rpc_pipe_client *result;
3572 struct sockaddr_un addr;
3573 NTSTATUS status;
3574 int fd;
3576 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3577 if (result == NULL) {
3578 return NT_STATUS_NO_MEMORY;
3581 result->abstract_syntax = *abstract_syntax;
3582 result->transfer_syntax = ndr_transfer_syntax;
3583 result->dispatch = cli_do_rpc_ndr;
3584 result->dispatch_send = cli_do_rpc_ndr_send;
3585 result->dispatch_recv = cli_do_rpc_ndr_recv;
3587 result->desthost = get_myname(result);
3588 result->srv_name_slash = talloc_asprintf_strupper_m(
3589 result, "\\\\%s", result->desthost);
3590 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3591 status = NT_STATUS_NO_MEMORY;
3592 goto fail;
3595 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3596 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3598 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3599 if (fd == -1) {
3600 status = map_nt_error_from_unix(errno);
3601 goto fail;
3604 ZERO_STRUCT(addr);
3605 addr.sun_family = AF_UNIX;
3606 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3608 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3609 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3610 strerror(errno)));
3611 close(fd);
3612 return map_nt_error_from_unix(errno);
3615 status = rpc_transport_sock_init(result, fd, &result->transport);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 close(fd);
3618 goto fail;
3621 result->transport->transport = NCALRPC;
3623 *presult = result;
3624 return NT_STATUS_OK;
3626 fail:
3627 TALLOC_FREE(result);
3628 return status;
3631 struct rpc_pipe_client_np_ref {
3632 struct cli_state *cli;
3633 struct rpc_pipe_client *pipe;
3636 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3638 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3639 return 0;
3642 /****************************************************************************
3643 Open a named pipe over SMB to a remote server.
3645 * CAVEAT CALLER OF THIS FUNCTION:
3646 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3647 * so be sure that this function is called AFTER any structure (vs pointer)
3648 * assignment of the cli. In particular, libsmbclient does structure
3649 * assignments of cli, which invalidates the data in the returned
3650 * rpc_pipe_client if this function is called before the structure assignment
3651 * of cli.
3653 ****************************************************************************/
3655 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3656 const struct ndr_syntax_id *abstract_syntax,
3657 struct rpc_pipe_client **presult)
3659 struct rpc_pipe_client *result;
3660 NTSTATUS status;
3661 struct rpc_pipe_client_np_ref *np_ref;
3663 /* sanity check to protect against crashes */
3665 if ( !cli ) {
3666 return NT_STATUS_INVALID_HANDLE;
3669 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3670 if (result == NULL) {
3671 return NT_STATUS_NO_MEMORY;
3674 result->abstract_syntax = *abstract_syntax;
3675 result->transfer_syntax = ndr_transfer_syntax;
3676 result->dispatch = cli_do_rpc_ndr;
3677 result->dispatch_send = cli_do_rpc_ndr_send;
3678 result->dispatch_recv = cli_do_rpc_ndr_recv;
3679 result->desthost = talloc_strdup(result, cli->desthost);
3680 result->srv_name_slash = talloc_asprintf_strupper_m(
3681 result, "\\\\%s", result->desthost);
3683 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3684 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3686 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3687 TALLOC_FREE(result);
3688 return NT_STATUS_NO_MEMORY;
3691 status = rpc_transport_np_init(result, cli, abstract_syntax,
3692 &result->transport);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 TALLOC_FREE(result);
3695 return status;
3698 result->transport->transport = NCACN_NP;
3700 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3701 if (np_ref == NULL) {
3702 TALLOC_FREE(result);
3703 return NT_STATUS_NO_MEMORY;
3705 np_ref->cli = cli;
3706 np_ref->pipe = result;
3708 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3709 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3711 *presult = result;
3712 return NT_STATUS_OK;
3715 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3716 struct rpc_cli_smbd_conn *conn,
3717 const struct ndr_syntax_id *syntax,
3718 struct rpc_pipe_client **presult)
3720 struct rpc_pipe_client *result;
3721 struct cli_pipe_auth_data *auth;
3722 NTSTATUS status;
3724 result = talloc(mem_ctx, struct rpc_pipe_client);
3725 if (result == NULL) {
3726 return NT_STATUS_NO_MEMORY;
3728 result->abstract_syntax = *syntax;
3729 result->transfer_syntax = ndr_transfer_syntax;
3730 result->dispatch = cli_do_rpc_ndr;
3731 result->dispatch_send = cli_do_rpc_ndr_send;
3732 result->dispatch_recv = cli_do_rpc_ndr_recv;
3733 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3734 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3736 result->desthost = talloc_strdup(result, global_myname());
3737 result->srv_name_slash = talloc_asprintf_strupper_m(
3738 result, "\\\\%s", global_myname());
3739 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3740 TALLOC_FREE(result);
3741 return NT_STATUS_NO_MEMORY;
3744 status = rpc_transport_smbd_init(result, conn, syntax,
3745 &result->transport);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3748 nt_errstr(status)));
3749 TALLOC_FREE(result);
3750 return status;
3753 status = rpccli_anon_bind_data(result, &auth);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3756 nt_errstr(status)));
3757 TALLOC_FREE(result);
3758 return status;
3761 status = rpc_pipe_bind(result, auth);
3762 if (!NT_STATUS_IS_OK(status)) {
3763 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3764 TALLOC_FREE(result);
3765 return status;
3768 result->transport->transport = NCACN_INTERNAL;
3770 *presult = result;
3771 return NT_STATUS_OK;
3774 /****************************************************************************
3775 Open a pipe to a remote server.
3776 ****************************************************************************/
3778 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3779 enum dcerpc_transport_t transport,
3780 const struct ndr_syntax_id *interface,
3781 struct rpc_pipe_client **presult)
3783 switch (transport) {
3784 case NCACN_IP_TCP:
3785 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3786 presult);
3787 case NCACN_NP:
3788 return rpc_pipe_open_np(cli, interface, presult);
3789 default:
3790 return NT_STATUS_NOT_IMPLEMENTED;
3794 /****************************************************************************
3795 Open a named pipe to an SMB server and bind anonymously.
3796 ****************************************************************************/
3798 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3799 enum dcerpc_transport_t transport,
3800 const struct ndr_syntax_id *interface,
3801 struct rpc_pipe_client **presult)
3803 struct rpc_pipe_client *result;
3804 struct cli_pipe_auth_data *auth;
3805 NTSTATUS status;
3807 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3808 if (!NT_STATUS_IS_OK(status)) {
3809 return status;
3812 status = rpccli_anon_bind_data(result, &auth);
3813 if (!NT_STATUS_IS_OK(status)) {
3814 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3815 nt_errstr(status)));
3816 TALLOC_FREE(result);
3817 return status;
3821 * This is a bit of an abstraction violation due to the fact that an
3822 * anonymous bind on an authenticated SMB inherits the user/domain
3823 * from the enclosing SMB creds
3826 TALLOC_FREE(auth->user_name);
3827 TALLOC_FREE(auth->domain);
3829 auth->user_name = talloc_strdup(auth, cli->user_name);
3830 auth->domain = talloc_strdup(auth, cli->domain);
3831 auth->user_session_key = data_blob_talloc(auth,
3832 cli->user_session_key.data,
3833 cli->user_session_key.length);
3835 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3836 TALLOC_FREE(result);
3837 return NT_STATUS_NO_MEMORY;
3840 status = rpc_pipe_bind(result, auth);
3841 if (!NT_STATUS_IS_OK(status)) {
3842 int lvl = 0;
3843 if (ndr_syntax_id_equal(interface,
3844 &ndr_table_dssetup.syntax_id)) {
3845 /* non AD domains just don't have this pipe, avoid
3846 * level 0 statement in that case - gd */
3847 lvl = 3;
3849 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3850 "%s failed with error %s\n",
3851 get_pipe_name_from_syntax(talloc_tos(), interface),
3852 nt_errstr(status) ));
3853 TALLOC_FREE(result);
3854 return status;
3857 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3858 "%s and bound anonymously.\n",
3859 get_pipe_name_from_syntax(talloc_tos(), interface),
3860 cli->desthost));
3862 *presult = result;
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 ****************************************************************************/
3869 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3870 const struct ndr_syntax_id *interface,
3871 struct rpc_pipe_client **presult)
3873 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3874 interface, presult);
3877 /****************************************************************************
3878 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3879 ****************************************************************************/
3881 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3882 const struct ndr_syntax_id *interface,
3883 enum dcerpc_transport_t transport,
3884 enum pipe_auth_type auth_type,
3885 enum dcerpc_AuthLevel auth_level,
3886 const char *domain,
3887 const char *username,
3888 const char *password,
3889 struct rpc_pipe_client **presult)
3891 struct rpc_pipe_client *result;
3892 struct cli_pipe_auth_data *auth;
3893 NTSTATUS status;
3895 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 return status;
3900 status = rpccli_ntlmssp_bind_data(
3901 result, auth_type, auth_level, domain, username,
3902 password, &auth);
3903 if (!NT_STATUS_IS_OK(status)) {
3904 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3905 nt_errstr(status)));
3906 goto err;
3909 status = rpc_pipe_bind(result, auth);
3910 if (!NT_STATUS_IS_OK(status)) {
3911 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3912 nt_errstr(status) ));
3913 goto err;
3916 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3917 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3918 get_pipe_name_from_syntax(talloc_tos(), interface),
3919 cli->desthost, domain, username ));
3921 *presult = result;
3922 return NT_STATUS_OK;
3924 err:
3926 TALLOC_FREE(result);
3927 return status;
3930 /****************************************************************************
3931 External interface.
3932 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3933 ****************************************************************************/
3935 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3936 const struct ndr_syntax_id *interface,
3937 enum dcerpc_transport_t transport,
3938 enum dcerpc_AuthLevel auth_level,
3939 const char *domain,
3940 const char *username,
3941 const char *password,
3942 struct rpc_pipe_client **presult)
3944 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3945 interface,
3946 transport,
3947 PIPE_AUTH_TYPE_NTLMSSP,
3948 auth_level,
3949 domain,
3950 username,
3951 password,
3952 presult);
3955 /****************************************************************************
3956 External interface.
3957 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3958 ****************************************************************************/
3960 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3961 const struct ndr_syntax_id *interface,
3962 enum dcerpc_transport_t transport,
3963 enum dcerpc_AuthLevel auth_level,
3964 const char *domain,
3965 const char *username,
3966 const char *password,
3967 struct rpc_pipe_client **presult)
3969 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3970 interface,
3971 transport,
3972 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3973 auth_level,
3974 domain,
3975 username,
3976 password,
3977 presult);
3980 /****************************************************************************
3981 Get a the schannel session key out of an already opened netlogon pipe.
3982 ****************************************************************************/
3983 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3984 struct cli_state *cli,
3985 const char *domain,
3986 uint32 *pneg_flags)
3988 enum netr_SchannelType sec_chan_type = 0;
3989 unsigned char machine_pwd[16];
3990 const char *machine_account;
3991 NTSTATUS status;
3993 /* Get the machine account credentials from secrets.tdb. */
3994 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3995 &sec_chan_type))
3997 DEBUG(0, ("get_schannel_session_key: could not fetch "
3998 "trust account password for domain '%s'\n",
3999 domain));
4000 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
4003 status = rpccli_netlogon_setup_creds(netlogon_pipe,
4004 cli->desthost, /* server name */
4005 domain, /* domain */
4006 global_myname(), /* client name */
4007 machine_account, /* machine account name */
4008 machine_pwd,
4009 sec_chan_type,
4010 pneg_flags);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 DEBUG(3, ("get_schannel_session_key_common: "
4014 "rpccli_netlogon_setup_creds failed with result %s "
4015 "to server %s, domain %s, machine account %s.\n",
4016 nt_errstr(status), cli->desthost, domain,
4017 machine_account ));
4018 return status;
4021 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
4022 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
4023 cli->desthost));
4024 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4027 return NT_STATUS_OK;;
4030 /****************************************************************************
4031 Open a netlogon pipe and get the schannel session key.
4032 Now exposed to external callers.
4033 ****************************************************************************/
4036 NTSTATUS get_schannel_session_key(struct cli_state *cli,
4037 const char *domain,
4038 uint32 *pneg_flags,
4039 struct rpc_pipe_client **presult)
4041 struct rpc_pipe_client *netlogon_pipe = NULL;
4042 NTSTATUS status;
4044 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
4045 &netlogon_pipe);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 return status;
4050 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4051 pneg_flags);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 TALLOC_FREE(netlogon_pipe);
4054 return status;
4057 *presult = netlogon_pipe;
4058 return NT_STATUS_OK;
4061 /****************************************************************************
4062 External interface.
4063 Open a named pipe to an SMB server and bind using schannel (bind type 68)
4064 using session_key. sign and seal.
4066 The *pdc will be stolen onto this new pipe
4067 ****************************************************************************/
4069 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
4070 const struct ndr_syntax_id *interface,
4071 enum dcerpc_transport_t transport,
4072 enum dcerpc_AuthLevel auth_level,
4073 const char *domain,
4074 struct netlogon_creds_CredentialState **pdc,
4075 struct rpc_pipe_client **presult)
4077 struct rpc_pipe_client *result;
4078 struct cli_pipe_auth_data *auth;
4079 NTSTATUS status;
4081 status = cli_rpc_pipe_open(cli, transport, interface, &result);
4082 if (!NT_STATUS_IS_OK(status)) {
4083 return status;
4086 status = rpccli_schannel_bind_data(result, domain, auth_level,
4087 *pdc, &auth);
4088 if (!NT_STATUS_IS_OK(status)) {
4089 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4090 nt_errstr(status)));
4091 TALLOC_FREE(result);
4092 return status;
4095 status = rpc_pipe_bind(result, auth);
4096 if (!NT_STATUS_IS_OK(status)) {
4097 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4098 "cli_rpc_pipe_bind failed with error %s\n",
4099 nt_errstr(status) ));
4100 TALLOC_FREE(result);
4101 return status;
4105 * The credentials on a new netlogon pipe are the ones we are passed
4106 * in - reference them in
4108 result->dc = talloc_move(result, pdc);
4110 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4111 "for domain %s and bound using schannel.\n",
4112 get_pipe_name_from_syntax(talloc_tos(), interface),
4113 cli->desthost, domain ));
4115 *presult = result;
4116 return NT_STATUS_OK;
4119 /****************************************************************************
4120 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4121 Fetch the session key ourselves using a temporary netlogon pipe. This
4122 version uses an ntlmssp auth bound netlogon pipe to get the key.
4123 ****************************************************************************/
4125 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4126 const char *domain,
4127 const char *username,
4128 const char *password,
4129 uint32 *pneg_flags,
4130 struct rpc_pipe_client **presult)
4132 struct rpc_pipe_client *netlogon_pipe = NULL;
4133 NTSTATUS status;
4135 status = cli_rpc_pipe_open_spnego_ntlmssp(
4136 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4137 DCERPC_AUTH_LEVEL_PRIVACY,
4138 domain, username, password, &netlogon_pipe);
4139 if (!NT_STATUS_IS_OK(status)) {
4140 return status;
4143 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4144 pneg_flags);
4145 if (!NT_STATUS_IS_OK(status)) {
4146 TALLOC_FREE(netlogon_pipe);
4147 return status;
4150 *presult = netlogon_pipe;
4151 return NT_STATUS_OK;
4154 /****************************************************************************
4155 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4156 Fetch the session key ourselves using a temporary netlogon pipe. This version
4157 uses an ntlmssp bind to get the session key.
4158 ****************************************************************************/
4160 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4161 const struct ndr_syntax_id *interface,
4162 enum dcerpc_transport_t transport,
4163 enum dcerpc_AuthLevel auth_level,
4164 const char *domain,
4165 const char *username,
4166 const char *password,
4167 struct rpc_pipe_client **presult)
4169 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4170 struct rpc_pipe_client *netlogon_pipe = NULL;
4171 struct rpc_pipe_client *result = NULL;
4172 NTSTATUS status;
4174 status = get_schannel_session_key_auth_ntlmssp(
4175 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4178 "key from server %s for domain %s.\n",
4179 cli->desthost, domain ));
4180 return status;
4183 status = cli_rpc_pipe_open_schannel_with_key(
4184 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4185 &result);
4187 /* Now we've bound using the session key we can close the netlog pipe. */
4188 TALLOC_FREE(netlogon_pipe);
4190 if (NT_STATUS_IS_OK(status)) {
4191 *presult = result;
4193 return status;
4196 /****************************************************************************
4197 Open a named pipe to an SMB server and bind using schannel (bind type 68).
4198 Fetch the session key ourselves using a temporary netlogon pipe.
4199 ****************************************************************************/
4201 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4202 const struct ndr_syntax_id *interface,
4203 enum dcerpc_transport_t transport,
4204 enum dcerpc_AuthLevel auth_level,
4205 const char *domain,
4206 struct rpc_pipe_client **presult)
4208 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4209 struct rpc_pipe_client *netlogon_pipe = NULL;
4210 struct rpc_pipe_client *result = NULL;
4211 NTSTATUS status;
4213 status = get_schannel_session_key(cli, domain, &neg_flags,
4214 &netlogon_pipe);
4215 if (!NT_STATUS_IS_OK(status)) {
4216 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4217 "key from server %s for domain %s.\n",
4218 cli->desthost, domain ));
4219 return status;
4222 status = cli_rpc_pipe_open_schannel_with_key(
4223 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4224 &result);
4226 /* Now we've bound using the session key we can close the netlog pipe. */
4227 TALLOC_FREE(netlogon_pipe);
4229 if (NT_STATUS_IS_OK(status)) {
4230 *presult = result;
4233 return status;
4236 /****************************************************************************
4237 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4238 The idea is this can be called with service_princ, username and password all
4239 NULL so long as the caller has a TGT.
4240 ****************************************************************************/
4242 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4243 const struct ndr_syntax_id *interface,
4244 enum dcerpc_AuthLevel auth_level,
4245 const char *service_princ,
4246 const char *username,
4247 const char *password,
4248 struct rpc_pipe_client **presult)
4250 #ifdef HAVE_KRB5
4251 struct rpc_pipe_client *result;
4252 struct cli_pipe_auth_data *auth;
4253 NTSTATUS status;
4255 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4256 if (!NT_STATUS_IS_OK(status)) {
4257 return status;
4260 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4261 username, password, &auth);
4262 if (!NT_STATUS_IS_OK(status)) {
4263 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4264 nt_errstr(status)));
4265 TALLOC_FREE(result);
4266 return status;
4269 status = rpc_pipe_bind(result, auth);
4270 if (!NT_STATUS_IS_OK(status)) {
4271 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4272 "with error %s\n", nt_errstr(status)));
4273 TALLOC_FREE(result);
4274 return status;
4277 *presult = result;
4278 return NT_STATUS_OK;
4279 #else
4280 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4281 return NT_STATUS_NOT_IMPLEMENTED;
4282 #endif
4285 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4286 struct rpc_pipe_client *cli,
4287 DATA_BLOB *session_key)
4289 if (!session_key || !cli) {
4290 return NT_STATUS_INVALID_PARAMETER;
4293 if (!cli->auth) {
4294 return NT_STATUS_INVALID_PARAMETER;
4297 switch (cli->auth->auth_type) {
4298 case PIPE_AUTH_TYPE_SCHANNEL:
4299 *session_key = data_blob_talloc(mem_ctx,
4300 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4301 break;
4302 case PIPE_AUTH_TYPE_NTLMSSP:
4303 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4304 *session_key = data_blob_talloc(mem_ctx,
4305 cli->auth->a_u.ntlmssp_state->session_key.data,
4306 cli->auth->a_u.ntlmssp_state->session_key.length);
4307 break;
4308 case PIPE_AUTH_TYPE_KRB5:
4309 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4310 *session_key = data_blob_talloc(mem_ctx,
4311 cli->auth->a_u.kerberos_auth->session_key.data,
4312 cli->auth->a_u.kerberos_auth->session_key.length);
4313 break;
4314 case PIPE_AUTH_TYPE_NONE:
4315 *session_key = data_blob_talloc(mem_ctx,
4316 cli->auth->user_session_key.data,
4317 cli->auth->user_session_key.length);
4318 break;
4319 default:
4320 return NT_STATUS_NO_USER_SESSION_KEY;
4323 return NT_STATUS_OK;