pyldb: Raise proper exception when attempting to assign a string to a dn
[Samba/fernandojvsilva.git] / source3 / rpc_client / cli_pipe.c
blob0f6471901813d173cb2554555346c574da6769ae
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "../libcli/auth/libcli_auth.h"
22 #include "librpc/gen_ndr/cli_epmapper.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_RPC_CLI
27 /*******************************************************************
28 interface/version dce/rpc pipe identification
29 ********************************************************************/
31 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
32 #define PIPE_SAMR "\\PIPE\\samr"
33 #define PIPE_WINREG "\\PIPE\\winreg"
34 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
35 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
36 #define PIPE_NTLSA "\\PIPE\\ntlsa"
37 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
38 #define PIPE_LSASS "\\PIPE\\lsass"
39 #define PIPE_LSARPC "\\PIPE\\lsarpc"
40 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
41 #define PIPE_NETDFS "\\PIPE\\netdfs"
42 #define PIPE_ECHO "\\PIPE\\rpcecho"
43 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
44 #define PIPE_EPM "\\PIPE\\epmapper"
45 #define PIPE_SVCCTL "\\PIPE\\svcctl"
46 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
47 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
48 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
51 * IMPORTANT!! If you update this structure, make sure to
52 * update the index #defines in smb.h.
55 static const struct pipe_id_info {
56 /* the names appear not to matter: the syntaxes _do_ matter */
58 const char *client_pipe;
59 const struct ndr_syntax_id *abstr_syntax; /* this one is the abstract syntax id */
60 } pipe_names [] =
62 { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
63 { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
64 { PIPE_SAMR, &ndr_table_samr.syntax_id },
65 { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
66 { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
67 { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
68 { PIPE_WINREG, &ndr_table_winreg.syntax_id },
69 { PIPE_SPOOLSS, &ndr_table_spoolss.syntax_id },
70 { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
71 { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
72 { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
73 { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
74 { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
75 { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
76 { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
77 { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
78 { NULL, NULL }
81 /****************************************************************************
82 Return the pipe name from the interface.
83 ****************************************************************************/
85 const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
87 char *guid_str;
88 const char *result;
89 int i;
90 for (i = 0; pipe_names[i].client_pipe; i++) {
91 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
92 interface)) {
93 return &pipe_names[i].client_pipe[5];
98 * Here we should ask \\epmapper, but for now our code is only
99 * interested in the known pipes mentioned in pipe_names[]
102 guid_str = GUID_string(talloc_tos(), &interface->uuid);
103 if (guid_str == NULL) {
104 return NULL;
106 result = talloc_asprintf(talloc_tos(), "Interface %s.%d", guid_str,
107 (int)interface->if_version);
108 TALLOC_FREE(guid_str);
110 if (result == NULL) {
111 return "PIPE";
113 return result;
116 /********************************************************************
117 Map internal value to wire value.
118 ********************************************************************/
120 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
122 switch (auth_type) {
124 case PIPE_AUTH_TYPE_NONE:
125 return RPC_ANONYMOUS_AUTH_TYPE;
127 case PIPE_AUTH_TYPE_NTLMSSP:
128 return RPC_NTLMSSP_AUTH_TYPE;
130 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
131 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
132 return RPC_SPNEGO_AUTH_TYPE;
134 case PIPE_AUTH_TYPE_SCHANNEL:
135 return RPC_SCHANNEL_AUTH_TYPE;
137 case PIPE_AUTH_TYPE_KRB5:
138 return RPC_KRB5_AUTH_TYPE;
140 default:
141 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
142 "auth type %u\n",
143 (unsigned int)auth_type ));
144 break;
146 return -1;
149 /********************************************************************
150 Pipe description for a DEBUG
151 ********************************************************************/
152 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
153 struct rpc_pipe_client *cli)
155 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
156 if (result == NULL) {
157 return "pipe";
159 return result;
162 /********************************************************************
163 Rpc pipe call id.
164 ********************************************************************/
166 static uint32 get_rpc_call_id(void)
168 static uint32 call_id = 0;
169 return ++call_id;
173 * Realloc pdu to have a least "size" bytes
176 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
178 size_t extra_size;
180 if (prs_data_size(pdu) >= size) {
181 return true;
184 extra_size = size - prs_data_size(pdu);
186 if (!prs_force_grow(pdu, extra_size)) {
187 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
188 "%d bytes.\n", (int)extra_size));
189 return false;
192 DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
193 (int)extra_size, prs_data_size(pdu)));
194 return true;
198 /*******************************************************************
199 Use SMBreadX to get rest of one fragment's worth of rpc data.
200 Reads the whole size or give an error message
201 ********************************************************************/
203 struct rpc_read_state {
204 struct event_context *ev;
205 struct rpc_cli_transport *transport;
206 uint8_t *data;
207 size_t size;
208 size_t num_read;
211 static void rpc_read_done(struct tevent_req *subreq);
213 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
214 struct event_context *ev,
215 struct rpc_cli_transport *transport,
216 uint8_t *data, size_t size)
218 struct tevent_req *req, *subreq;
219 struct rpc_read_state *state;
221 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
222 if (req == NULL) {
223 return NULL;
225 state->ev = ev;
226 state->transport = transport;
227 state->data = data;
228 state->size = size;
229 state->num_read = 0;
231 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
233 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
234 transport->priv);
235 if (subreq == NULL) {
236 goto fail;
238 tevent_req_set_callback(subreq, rpc_read_done, req);
239 return req;
241 fail:
242 TALLOC_FREE(req);
243 return NULL;
246 static void rpc_read_done(struct tevent_req *subreq)
248 struct tevent_req *req = tevent_req_callback_data(
249 subreq, struct tevent_req);
250 struct rpc_read_state *state = tevent_req_data(
251 req, struct rpc_read_state);
252 NTSTATUS status;
253 ssize_t received;
255 status = state->transport->read_recv(subreq, &received);
256 TALLOC_FREE(subreq);
257 if (!NT_STATUS_IS_OK(status)) {
258 tevent_req_nterror(req, status);
259 return;
262 state->num_read += received;
263 if (state->num_read == state->size) {
264 tevent_req_done(req);
265 return;
268 subreq = state->transport->read_send(state, state->ev,
269 state->data + state->num_read,
270 state->size - state->num_read,
271 state->transport->priv);
272 if (tevent_req_nomem(subreq, req)) {
273 return;
275 tevent_req_set_callback(subreq, rpc_read_done, req);
278 static NTSTATUS rpc_read_recv(struct tevent_req *req)
280 return tevent_req_simple_recv_ntstatus(req);
283 struct rpc_write_state {
284 struct event_context *ev;
285 struct rpc_cli_transport *transport;
286 const uint8_t *data;
287 size_t size;
288 size_t num_written;
291 static void rpc_write_done(struct tevent_req *subreq);
293 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
294 struct event_context *ev,
295 struct rpc_cli_transport *transport,
296 const uint8_t *data, size_t size)
298 struct tevent_req *req, *subreq;
299 struct rpc_write_state *state;
301 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
302 if (req == NULL) {
303 return NULL;
305 state->ev = ev;
306 state->transport = transport;
307 state->data = data;
308 state->size = size;
309 state->num_written = 0;
311 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
313 subreq = transport->write_send(state, ev, data, size, transport->priv);
314 if (subreq == NULL) {
315 goto fail;
317 tevent_req_set_callback(subreq, rpc_write_done, req);
318 return req;
319 fail:
320 TALLOC_FREE(req);
321 return NULL;
324 static void rpc_write_done(struct tevent_req *subreq)
326 struct tevent_req *req = tevent_req_callback_data(
327 subreq, struct tevent_req);
328 struct rpc_write_state *state = tevent_req_data(
329 req, struct rpc_write_state);
330 NTSTATUS status;
331 ssize_t written;
333 status = state->transport->write_recv(subreq, &written);
334 TALLOC_FREE(subreq);
335 if (!NT_STATUS_IS_OK(status)) {
336 tevent_req_nterror(req, status);
337 return;
340 state->num_written += written;
342 if (state->num_written == state->size) {
343 tevent_req_done(req);
344 return;
347 subreq = state->transport->write_send(state, state->ev,
348 state->data + state->num_written,
349 state->size - state->num_written,
350 state->transport->priv);
351 if (tevent_req_nomem(subreq, req)) {
352 return;
354 tevent_req_set_callback(subreq, rpc_write_done, req);
357 static NTSTATUS rpc_write_recv(struct tevent_req *req)
359 return tevent_req_simple_recv_ntstatus(req);
363 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
364 struct rpc_hdr_info *prhdr,
365 prs_struct *pdu)
368 * This next call sets the endian bit correctly in current_pdu. We
369 * will propagate this to rbuf later.
372 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, pdu, 0)) {
373 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
374 return NT_STATUS_BUFFER_TOO_SMALL;
377 if (prhdr->frag_len > cli->max_recv_frag) {
378 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
379 " we only allow %d\n", (int)prhdr->frag_len,
380 (int)cli->max_recv_frag));
381 return NT_STATUS_BUFFER_TOO_SMALL;
384 return NT_STATUS_OK;
387 /****************************************************************************
388 Try and get a PDU's worth of data from current_pdu. If not, then read more
389 from the wire.
390 ****************************************************************************/
392 struct get_complete_frag_state {
393 struct event_context *ev;
394 struct rpc_pipe_client *cli;
395 struct rpc_hdr_info *prhdr;
396 prs_struct *pdu;
399 static void get_complete_frag_got_header(struct tevent_req *subreq);
400 static void get_complete_frag_got_rest(struct tevent_req *subreq);
402 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
403 struct event_context *ev,
404 struct rpc_pipe_client *cli,
405 struct rpc_hdr_info *prhdr,
406 prs_struct *pdu)
408 struct tevent_req *req, *subreq;
409 struct get_complete_frag_state *state;
410 uint32_t pdu_len;
411 NTSTATUS status;
413 req = tevent_req_create(mem_ctx, &state,
414 struct get_complete_frag_state);
415 if (req == NULL) {
416 return NULL;
418 state->ev = ev;
419 state->cli = cli;
420 state->prhdr = prhdr;
421 state->pdu = pdu;
423 pdu_len = prs_data_size(pdu);
424 if (pdu_len < RPC_HEADER_LEN) {
425 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
426 status = NT_STATUS_NO_MEMORY;
427 goto post_status;
429 subreq = rpc_read_send(
430 state, state->ev,
431 state->cli->transport,
432 (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
433 RPC_HEADER_LEN - pdu_len);
434 if (subreq == NULL) {
435 status = NT_STATUS_NO_MEMORY;
436 goto post_status;
438 tevent_req_set_callback(subreq, get_complete_frag_got_header,
439 req);
440 return req;
443 status = parse_rpc_header(cli, prhdr, pdu);
444 if (!NT_STATUS_IS_OK(status)) {
445 goto post_status;
449 * Ensure we have frag_len bytes of data.
451 if (pdu_len < prhdr->frag_len) {
452 if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
453 status = NT_STATUS_NO_MEMORY;
454 goto post_status;
456 subreq = rpc_read_send(state, state->ev,
457 state->cli->transport,
458 (uint8_t *)(prs_data_p(pdu) + pdu_len),
459 prhdr->frag_len - pdu_len);
460 if (subreq == NULL) {
461 status = NT_STATUS_NO_MEMORY;
462 goto post_status;
464 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
465 req);
466 return req;
469 status = NT_STATUS_OK;
470 post_status:
471 if (NT_STATUS_IS_OK(status)) {
472 tevent_req_done(req);
473 } else {
474 tevent_req_nterror(req, status);
476 return tevent_req_post(req, ev);
479 static void get_complete_frag_got_header(struct tevent_req *subreq)
481 struct tevent_req *req = tevent_req_callback_data(
482 subreq, struct tevent_req);
483 struct get_complete_frag_state *state = tevent_req_data(
484 req, struct get_complete_frag_state);
485 NTSTATUS status;
487 status = rpc_read_recv(subreq);
488 TALLOC_FREE(subreq);
489 if (!NT_STATUS_IS_OK(status)) {
490 tevent_req_nterror(req, status);
491 return;
494 status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
495 if (!NT_STATUS_IS_OK(status)) {
496 tevent_req_nterror(req, status);
497 return;
500 if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
501 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
502 return;
506 * We're here in this piece of code because we've read exactly
507 * RPC_HEADER_LEN bytes into state->pdu.
510 subreq = rpc_read_send(
511 state, state->ev, state->cli->transport,
512 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
513 state->prhdr->frag_len - RPC_HEADER_LEN);
514 if (tevent_req_nomem(subreq, req)) {
515 return;
517 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
520 static void get_complete_frag_got_rest(struct tevent_req *subreq)
522 struct tevent_req *req = tevent_req_callback_data(
523 subreq, struct tevent_req);
524 NTSTATUS status;
526 status = rpc_read_recv(subreq);
527 TALLOC_FREE(subreq);
528 if (!NT_STATUS_IS_OK(status)) {
529 tevent_req_nterror(req, status);
530 return;
532 tevent_req_done(req);
535 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
537 return tevent_req_simple_recv_ntstatus(req);
540 /****************************************************************************
541 NTLMSSP specific sign/seal.
542 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
543 In fact I should probably abstract these into identical pieces of code... JRA.
544 ****************************************************************************/
546 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
547 prs_struct *current_pdu,
548 uint8 *p_ss_padding_len)
550 RPC_HDR_AUTH auth_info;
551 uint32 save_offset = prs_offset(current_pdu);
552 uint32 auth_len = prhdr->auth_len;
553 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
554 unsigned char *data = NULL;
555 size_t data_len;
556 unsigned char *full_packet_data = NULL;
557 size_t full_packet_data_len;
558 DATA_BLOB auth_blob;
559 NTSTATUS status;
561 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
562 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
563 return NT_STATUS_OK;
566 if (!ntlmssp_state) {
567 return NT_STATUS_INVALID_PARAMETER;
570 /* Ensure there's enough data for an authenticated response. */
571 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
572 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
573 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
574 (unsigned int)auth_len ));
575 return NT_STATUS_BUFFER_TOO_SMALL;
579 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
580 * after the RPC header.
581 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
582 * functions as NTLMv2 checks the rpc headers also.
585 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
586 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
588 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
589 full_packet_data_len = prhdr->frag_len - auth_len;
591 /* Pull the auth header and the following data into a blob. */
592 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
593 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
594 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
595 return NT_STATUS_BUFFER_TOO_SMALL;
598 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
599 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
600 return NT_STATUS_BUFFER_TOO_SMALL;
603 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
604 auth_blob.length = auth_len;
606 switch (cli->auth->auth_level) {
607 case PIPE_AUTH_LEVEL_PRIVACY:
608 /* Data is encrypted. */
609 status = ntlmssp_unseal_packet(ntlmssp_state,
610 data, data_len,
611 full_packet_data,
612 full_packet_data_len,
613 &auth_blob);
614 if (!NT_STATUS_IS_OK(status)) {
615 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
616 "packet from %s. Error was %s.\n",
617 rpccli_pipe_txt(debug_ctx(), cli),
618 nt_errstr(status) ));
619 return status;
621 break;
622 case PIPE_AUTH_LEVEL_INTEGRITY:
623 /* Data is signed. */
624 status = ntlmssp_check_packet(ntlmssp_state,
625 data, data_len,
626 full_packet_data,
627 full_packet_data_len,
628 &auth_blob);
629 if (!NT_STATUS_IS_OK(status)) {
630 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
631 "packet from %s. Error was %s.\n",
632 rpccli_pipe_txt(debug_ctx(), cli),
633 nt_errstr(status) ));
634 return status;
636 break;
637 default:
638 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
639 "auth level %d\n", cli->auth->auth_level));
640 return NT_STATUS_INVALID_INFO_CLASS;
644 * Return the current pointer to the data offset.
647 if(!prs_set_offset(current_pdu, save_offset)) {
648 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
649 (unsigned int)save_offset ));
650 return NT_STATUS_BUFFER_TOO_SMALL;
654 * Remember the padding length. We must remove it from the real data
655 * stream once the sign/seal is done.
658 *p_ss_padding_len = auth_info.auth_pad_len;
660 return NT_STATUS_OK;
663 /****************************************************************************
664 schannel specific sign/seal.
665 ****************************************************************************/
667 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
668 prs_struct *current_pdu,
669 uint8 *p_ss_padding_len)
671 RPC_HDR_AUTH auth_info;
672 RPC_AUTH_SCHANNEL_CHK schannel_chk;
673 uint32 auth_len = prhdr->auth_len;
674 uint32 save_offset = prs_offset(current_pdu);
675 struct schannel_auth_struct *schannel_auth =
676 cli->auth->a_u.schannel_auth;
677 uint32 data_len;
679 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
680 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
681 return NT_STATUS_OK;
684 if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
685 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
686 return NT_STATUS_INVALID_PARAMETER;
689 if (!schannel_auth) {
690 return NT_STATUS_INVALID_PARAMETER;
693 /* Ensure there's enough data for an authenticated response. */
694 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
695 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
696 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
697 (unsigned int)auth_len ));
698 return NT_STATUS_INVALID_PARAMETER;
701 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
703 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
704 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
705 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
706 return NT_STATUS_BUFFER_TOO_SMALL;
709 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
710 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
711 return NT_STATUS_BUFFER_TOO_SMALL;
714 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
715 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
716 auth_info.auth_type));
717 return NT_STATUS_BUFFER_TOO_SMALL;
720 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
721 &schannel_chk, current_pdu, 0)) {
722 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
723 return NT_STATUS_BUFFER_TOO_SMALL;
726 if (!schannel_decode(schannel_auth,
727 cli->auth->auth_level,
728 SENDER_IS_ACCEPTOR,
729 &schannel_chk,
730 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
731 data_len)) {
732 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
733 "Connection to %s.\n",
734 rpccli_pipe_txt(debug_ctx(), cli)));
735 return NT_STATUS_INVALID_PARAMETER;
738 /* The sequence number gets incremented on both send and receive. */
739 schannel_auth->seq_num++;
742 * Return the current pointer to the data offset.
745 if(!prs_set_offset(current_pdu, save_offset)) {
746 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
747 (unsigned int)save_offset ));
748 return NT_STATUS_BUFFER_TOO_SMALL;
752 * Remember the padding length. We must remove it from the real data
753 * stream once the sign/seal is done.
756 *p_ss_padding_len = auth_info.auth_pad_len;
758 return NT_STATUS_OK;
761 /****************************************************************************
762 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
763 ****************************************************************************/
765 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
766 prs_struct *current_pdu,
767 uint8 *p_ss_padding_len)
769 NTSTATUS ret = NT_STATUS_OK;
771 /* Paranioa checks for auth_len. */
772 if (prhdr->auth_len) {
773 if (prhdr->auth_len > prhdr->frag_len) {
774 return NT_STATUS_INVALID_PARAMETER;
777 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
778 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
779 /* Integer wrap attempt. */
780 return NT_STATUS_INVALID_PARAMETER;
785 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
788 switch(cli->auth->auth_type) {
789 case PIPE_AUTH_TYPE_NONE:
790 if (prhdr->auth_len) {
791 DEBUG(3, ("cli_pipe_validate_rpc_response: "
792 "Connection to %s - got non-zero "
793 "auth len %u.\n",
794 rpccli_pipe_txt(debug_ctx(), cli),
795 (unsigned int)prhdr->auth_len ));
796 return NT_STATUS_INVALID_PARAMETER;
798 break;
800 case PIPE_AUTH_TYPE_NTLMSSP:
801 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
802 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
803 if (!NT_STATUS_IS_OK(ret)) {
804 return ret;
806 break;
808 case PIPE_AUTH_TYPE_SCHANNEL:
809 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
810 if (!NT_STATUS_IS_OK(ret)) {
811 return ret;
813 break;
815 case PIPE_AUTH_TYPE_KRB5:
816 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
817 default:
818 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
819 "to %s - unknown internal auth type %u.\n",
820 rpccli_pipe_txt(debug_ctx(), cli),
821 cli->auth->auth_type ));
822 return NT_STATUS_INVALID_INFO_CLASS;
825 return NT_STATUS_OK;
828 /****************************************************************************
829 Do basic authentication checks on an incoming pdu.
830 ****************************************************************************/
832 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
833 prs_struct *current_pdu,
834 uint8 expected_pkt_type,
835 char **ppdata,
836 uint32 *pdata_len,
837 prs_struct *return_data)
840 NTSTATUS ret = NT_STATUS_OK;
841 uint32 current_pdu_len = prs_data_size(current_pdu);
843 if (current_pdu_len != prhdr->frag_len) {
844 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
845 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
846 return NT_STATUS_INVALID_PARAMETER;
850 * Point the return values at the real data including the RPC
851 * header. Just in case the caller wants it.
853 *ppdata = prs_data_p(current_pdu);
854 *pdata_len = current_pdu_len;
856 /* Ensure we have the correct type. */
857 switch (prhdr->pkt_type) {
858 case RPC_ALTCONTRESP:
859 case RPC_BINDACK:
861 /* Alter context and bind ack share the same packet definitions. */
862 break;
865 case RPC_RESPONSE:
867 RPC_HDR_RESP rhdr_resp;
868 uint8 ss_padding_len = 0;
870 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
871 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
872 return NT_STATUS_BUFFER_TOO_SMALL;
875 /* Here's where we deal with incoming sign/seal. */
876 ret = cli_pipe_validate_rpc_response(cli, prhdr,
877 current_pdu, &ss_padding_len);
878 if (!NT_STATUS_IS_OK(ret)) {
879 return ret;
882 /* Point the return values at the NDR data. Remember to remove any ss padding. */
883 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
885 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
886 return NT_STATUS_BUFFER_TOO_SMALL;
889 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
891 /* Remember to remove the auth footer. */
892 if (prhdr->auth_len) {
893 /* We've already done integer wrap tests on auth_len in
894 cli_pipe_validate_rpc_response(). */
895 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
896 return NT_STATUS_BUFFER_TOO_SMALL;
898 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
901 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
902 current_pdu_len, *pdata_len, ss_padding_len ));
905 * If this is the first reply, and the allocation hint is reasonably, try and
906 * set up the return_data parse_struct to the correct size.
909 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
910 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
911 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
912 "too large to allocate\n",
913 (unsigned int)rhdr_resp.alloc_hint ));
914 return NT_STATUS_NO_MEMORY;
918 break;
921 case RPC_BINDNACK:
922 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
923 "received from %s!\n",
924 rpccli_pipe_txt(debug_ctx(), cli)));
925 /* Use this for now... */
926 return NT_STATUS_NETWORK_ACCESS_DENIED;
928 case RPC_FAULT:
930 RPC_HDR_RESP rhdr_resp;
931 RPC_HDR_FAULT fault_resp;
933 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
934 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
935 return NT_STATUS_BUFFER_TOO_SMALL;
938 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
939 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
940 return NT_STATUS_BUFFER_TOO_SMALL;
943 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
944 "code %s received from %s!\n",
945 dcerpc_errstr(debug_ctx(), NT_STATUS_V(fault_resp.status)),
946 rpccli_pipe_txt(debug_ctx(), cli)));
947 if (NT_STATUS_IS_OK(fault_resp.status)) {
948 return NT_STATUS_UNSUCCESSFUL;
949 } else {
950 return fault_resp.status;
954 default:
955 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
956 "from %s!\n",
957 (unsigned int)prhdr->pkt_type,
958 rpccli_pipe_txt(debug_ctx(), cli)));
959 return NT_STATUS_INVALID_INFO_CLASS;
962 if (prhdr->pkt_type != expected_pkt_type) {
963 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
964 "got an unexpected RPC packet type - %u, not %u\n",
965 rpccli_pipe_txt(debug_ctx(), cli),
966 prhdr->pkt_type,
967 expected_pkt_type));
968 return NT_STATUS_INVALID_INFO_CLASS;
971 /* Do this just before return - we don't want to modify any rpc header
972 data before now as we may have needed to do cryptographic actions on
973 it before. */
975 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
976 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
977 "setting fragment first/last ON.\n"));
978 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
981 return NT_STATUS_OK;
984 /****************************************************************************
985 Ensure we eat the just processed pdu from the current_pdu prs_struct.
986 Normally the frag_len and buffer size will match, but on the first trans
987 reply there is a theoretical chance that buffer size > frag_len, so we must
988 deal with that.
989 ****************************************************************************/
991 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
993 uint32 current_pdu_len = prs_data_size(current_pdu);
995 if (current_pdu_len < prhdr->frag_len) {
996 return NT_STATUS_BUFFER_TOO_SMALL;
999 /* Common case. */
1000 if (current_pdu_len == (uint32)prhdr->frag_len) {
1001 prs_mem_free(current_pdu);
1002 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1003 /* Make current_pdu dynamic with no memory. */
1004 prs_give_memory(current_pdu, 0, 0, True);
1005 return NT_STATUS_OK;
1009 * Oh no ! More data in buffer than we processed in current pdu.
1010 * Cheat. Move the data down and shrink the buffer.
1013 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1014 current_pdu_len - prhdr->frag_len);
1016 /* Remember to set the read offset back to zero. */
1017 prs_set_offset(current_pdu, 0);
1019 /* Shrink the buffer. */
1020 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1021 return NT_STATUS_BUFFER_TOO_SMALL;
1024 return NT_STATUS_OK;
1027 /****************************************************************************
1028 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
1029 ****************************************************************************/
1031 struct cli_api_pipe_state {
1032 struct event_context *ev;
1033 struct rpc_cli_transport *transport;
1034 uint8_t *rdata;
1035 uint32_t rdata_len;
1038 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1039 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1040 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1042 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1043 struct event_context *ev,
1044 struct rpc_cli_transport *transport,
1045 uint8_t *data, size_t data_len,
1046 uint32_t max_rdata_len)
1048 struct tevent_req *req, *subreq;
1049 struct cli_api_pipe_state *state;
1050 NTSTATUS status;
1052 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1053 if (req == NULL) {
1054 return NULL;
1056 state->ev = ev;
1057 state->transport = transport;
1059 if (max_rdata_len < RPC_HEADER_LEN) {
1061 * For a RPC reply we always need at least RPC_HEADER_LEN
1062 * bytes. We check this here because we will receive
1063 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1065 status = NT_STATUS_INVALID_PARAMETER;
1066 goto post_status;
1069 if (transport->trans_send != NULL) {
1070 subreq = transport->trans_send(state, ev, data, data_len,
1071 max_rdata_len, transport->priv);
1072 if (subreq == NULL) {
1073 goto fail;
1075 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1076 return req;
1080 * If the transport does not provide a "trans" routine, i.e. for
1081 * example the ncacn_ip_tcp transport, do the write/read step here.
1084 subreq = rpc_write_send(state, ev, transport, data, data_len);
1085 if (subreq == NULL) {
1086 goto fail;
1088 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1089 return req;
1091 status = NT_STATUS_INVALID_PARAMETER;
1093 post_status:
1094 tevent_req_nterror(req, status);
1095 return tevent_req_post(req, ev);
1096 fail:
1097 TALLOC_FREE(req);
1098 return NULL;
1101 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1103 struct tevent_req *req = tevent_req_callback_data(
1104 subreq, struct tevent_req);
1105 struct cli_api_pipe_state *state = tevent_req_data(
1106 req, struct cli_api_pipe_state);
1107 NTSTATUS status;
1109 status = state->transport->trans_recv(subreq, state, &state->rdata,
1110 &state->rdata_len);
1111 TALLOC_FREE(subreq);
1112 if (!NT_STATUS_IS_OK(status)) {
1113 tevent_req_nterror(req, status);
1114 return;
1116 tevent_req_done(req);
1119 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1121 struct tevent_req *req = tevent_req_callback_data(
1122 subreq, struct tevent_req);
1123 struct cli_api_pipe_state *state = tevent_req_data(
1124 req, struct cli_api_pipe_state);
1125 NTSTATUS status;
1127 status = rpc_write_recv(subreq);
1128 TALLOC_FREE(subreq);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 tevent_req_nterror(req, status);
1131 return;
1134 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1135 if (tevent_req_nomem(state->rdata, req)) {
1136 return;
1140 * We don't need to use rpc_read_send here, the upper layer will cope
1141 * with a short read, transport->trans_send could also return less
1142 * than state->max_rdata_len.
1144 subreq = state->transport->read_send(state, state->ev, state->rdata,
1145 RPC_HEADER_LEN,
1146 state->transport->priv);
1147 if (tevent_req_nomem(subreq, req)) {
1148 return;
1150 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1153 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1155 struct tevent_req *req = tevent_req_callback_data(
1156 subreq, struct tevent_req);
1157 struct cli_api_pipe_state *state = tevent_req_data(
1158 req, struct cli_api_pipe_state);
1159 NTSTATUS status;
1160 ssize_t received;
1162 status = state->transport->read_recv(subreq, &received);
1163 TALLOC_FREE(subreq);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 tevent_req_nterror(req, status);
1166 return;
1168 state->rdata_len = received;
1169 tevent_req_done(req);
1172 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1173 uint8_t **prdata, uint32_t *prdata_len)
1175 struct cli_api_pipe_state *state = tevent_req_data(
1176 req, struct cli_api_pipe_state);
1177 NTSTATUS status;
1179 if (tevent_req_is_nterror(req, &status)) {
1180 return status;
1183 *prdata = talloc_move(mem_ctx, &state->rdata);
1184 *prdata_len = state->rdata_len;
1185 return NT_STATUS_OK;
1188 /****************************************************************************
1189 Send data on an rpc pipe via trans. The prs_struct data must be the last
1190 pdu fragment of an NDR data stream.
1192 Receive response data from an rpc pipe, which may be large...
1194 Read the first fragment: unfortunately have to use SMBtrans for the first
1195 bit, then SMBreadX for subsequent bits.
1197 If first fragment received also wasn't the last fragment, continue
1198 getting fragments until we _do_ receive the last fragment.
1200 Request/Response PDU's look like the following...
1202 |<------------------PDU len----------------------------------------------->|
1203 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1205 +------------+-----------------+-------------+---------------+-------------+
1206 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
1207 +------------+-----------------+-------------+---------------+-------------+
1209 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1210 signing & sealing being negotiated.
1212 ****************************************************************************/
1214 struct rpc_api_pipe_state {
1215 struct event_context *ev;
1216 struct rpc_pipe_client *cli;
1217 uint8_t expected_pkt_type;
1219 prs_struct incoming_frag;
1220 struct rpc_hdr_info rhdr;
1222 prs_struct incoming_pdu; /* Incoming reply */
1223 uint32_t incoming_pdu_offset;
1226 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1228 prs_mem_free(&state->incoming_frag);
1229 prs_mem_free(&state->incoming_pdu);
1230 return 0;
1233 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1234 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1236 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1237 struct event_context *ev,
1238 struct rpc_pipe_client *cli,
1239 prs_struct *data, /* Outgoing PDU */
1240 uint8_t expected_pkt_type)
1242 struct tevent_req *req, *subreq;
1243 struct rpc_api_pipe_state *state;
1244 uint16_t max_recv_frag;
1245 NTSTATUS status;
1247 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1248 if (req == NULL) {
1249 return NULL;
1251 state->ev = ev;
1252 state->cli = cli;
1253 state->expected_pkt_type = expected_pkt_type;
1254 state->incoming_pdu_offset = 0;
1256 prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1258 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1259 /* Make incoming_pdu dynamic with no memory. */
1260 prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1262 talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1265 * Ensure we're not sending too much.
1267 if (prs_offset(data) > cli->max_xmit_frag) {
1268 status = NT_STATUS_INVALID_PARAMETER;
1269 goto post_status;
1272 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
1274 max_recv_frag = cli->max_recv_frag;
1276 #ifdef DEVELOPER
1277 max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1278 #endif
1280 subreq = cli_api_pipe_send(state, ev, cli->transport,
1281 (uint8_t *)prs_data_p(data),
1282 prs_offset(data), max_recv_frag);
1283 if (subreq == NULL) {
1284 goto fail;
1286 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1287 return req;
1289 post_status:
1290 tevent_req_nterror(req, status);
1291 return tevent_req_post(req, ev);
1292 fail:
1293 TALLOC_FREE(req);
1294 return NULL;
1297 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1299 struct tevent_req *req = tevent_req_callback_data(
1300 subreq, struct tevent_req);
1301 struct rpc_api_pipe_state *state = tevent_req_data(
1302 req, struct rpc_api_pipe_state);
1303 NTSTATUS status;
1304 uint8_t *rdata = NULL;
1305 uint32_t rdata_len = 0;
1306 char *rdata_copy;
1308 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1309 TALLOC_FREE(subreq);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1312 tevent_req_nterror(req, status);
1313 return;
1316 if (rdata == NULL) {
1317 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1318 rpccli_pipe_txt(debug_ctx(), state->cli)));
1319 tevent_req_done(req);
1320 return;
1324 * Give the memory received from cli_trans as dynamic to the current
1325 * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
1326 * :-(
1328 rdata_copy = (char *)memdup(rdata, rdata_len);
1329 TALLOC_FREE(rdata);
1330 if (tevent_req_nomem(rdata_copy, req)) {
1331 return;
1333 prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
1335 /* Ensure we have enough data for a pdu. */
1336 subreq = get_complete_frag_send(state, state->ev, state->cli,
1337 &state->rhdr, &state->incoming_frag);
1338 if (tevent_req_nomem(subreq, req)) {
1339 return;
1341 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1344 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1346 struct tevent_req *req = tevent_req_callback_data(
1347 subreq, struct tevent_req);
1348 struct rpc_api_pipe_state *state = tevent_req_data(
1349 req, struct rpc_api_pipe_state);
1350 NTSTATUS status;
1351 char *rdata = NULL;
1352 uint32_t rdata_len = 0;
1354 status = get_complete_frag_recv(subreq);
1355 TALLOC_FREE(subreq);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 DEBUG(5, ("get_complete_frag failed: %s\n",
1358 nt_errstr(status)));
1359 tevent_req_nterror(req, status);
1360 return;
1363 status = cli_pipe_validate_current_pdu(
1364 state->cli, &state->rhdr, &state->incoming_frag,
1365 state->expected_pkt_type, &rdata, &rdata_len,
1366 &state->incoming_pdu);
1368 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1369 (unsigned)prs_data_size(&state->incoming_frag),
1370 (unsigned)state->incoming_pdu_offset,
1371 nt_errstr(status)));
1373 if (!NT_STATUS_IS_OK(status)) {
1374 tevent_req_nterror(req, status);
1375 return;
1378 if ((state->rhdr.flags & RPC_FLG_FIRST)
1379 && (state->rhdr.pack_type[0] == 0)) {
1381 * Set the data type correctly for big-endian data on the
1382 * first packet.
1384 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1385 "big-endian.\n",
1386 rpccli_pipe_txt(debug_ctx(), state->cli)));
1387 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1390 * Check endianness on subsequent packets.
1392 if (state->incoming_frag.bigendian_data
1393 != state->incoming_pdu.bigendian_data) {
1394 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1395 "%s\n",
1396 state->incoming_pdu.bigendian_data?"big":"little",
1397 state->incoming_frag.bigendian_data?"big":"little"));
1398 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 return;
1402 /* Now copy the data portion out of the pdu into rbuf. */
1403 if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1404 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1405 return;
1408 memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1409 rdata, (size_t)rdata_len);
1410 state->incoming_pdu_offset += rdata_len;
1412 status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1413 &state->incoming_frag);
1414 if (!NT_STATUS_IS_OK(status)) {
1415 tevent_req_nterror(req, status);
1416 return;
1419 if (state->rhdr.flags & RPC_FLG_LAST) {
1420 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1421 rpccli_pipe_txt(debug_ctx(), state->cli),
1422 (unsigned)prs_data_size(&state->incoming_pdu)));
1423 tevent_req_done(req);
1424 return;
1427 subreq = get_complete_frag_send(state, state->ev, state->cli,
1428 &state->rhdr, &state->incoming_frag);
1429 if (tevent_req_nomem(subreq, req)) {
1430 return;
1432 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1435 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1436 prs_struct *reply_pdu)
1438 struct rpc_api_pipe_state *state = tevent_req_data(
1439 req, struct rpc_api_pipe_state);
1440 NTSTATUS status;
1442 if (tevent_req_is_nterror(req, &status)) {
1443 return status;
1446 *reply_pdu = state->incoming_pdu;
1447 reply_pdu->mem_ctx = mem_ctx;
1450 * Prevent state->incoming_pdu from being freed in
1451 * rpc_api_pipe_state_destructor()
1453 prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1455 return NT_STATUS_OK;
1458 /*******************************************************************
1459 Creates krb5 auth bind.
1460 ********************************************************************/
1462 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1463 enum pipe_auth_level auth_level,
1464 RPC_HDR_AUTH *pauth_out,
1465 prs_struct *auth_data)
1467 #ifdef HAVE_KRB5
1468 int ret;
1469 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1470 DATA_BLOB tkt = data_blob_null;
1471 DATA_BLOB tkt_wrapped = data_blob_null;
1473 /* We may change the pad length before marshalling. */
1474 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
1476 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1477 a->service_principal ));
1479 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1481 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1482 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
1484 if (ret) {
1485 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1486 "failed with %s\n",
1487 a->service_principal,
1488 error_message(ret) ));
1490 data_blob_free(&tkt);
1491 prs_mem_free(auth_data);
1492 return NT_STATUS_INVALID_PARAMETER;
1495 /* wrap that up in a nice GSS-API wrapping */
1496 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1498 data_blob_free(&tkt);
1500 /* Auth len in the rpc header doesn't include auth_header. */
1501 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1502 data_blob_free(&tkt_wrapped);
1503 prs_mem_free(auth_data);
1504 return NT_STATUS_NO_MEMORY;
1507 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1508 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1510 data_blob_free(&tkt_wrapped);
1511 return NT_STATUS_OK;
1512 #else
1513 return NT_STATUS_INVALID_PARAMETER;
1514 #endif
1517 /*******************************************************************
1518 Creates SPNEGO NTLMSSP auth bind.
1519 ********************************************************************/
1521 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1522 enum pipe_auth_level auth_level,
1523 RPC_HDR_AUTH *pauth_out,
1524 prs_struct *auth_data)
1526 NTSTATUS nt_status;
1527 DATA_BLOB null_blob = data_blob_null;
1528 DATA_BLOB request = data_blob_null;
1529 DATA_BLOB spnego_msg = data_blob_null;
1531 /* We may change the pad length before marshalling. */
1532 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1534 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1535 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1536 null_blob,
1537 &request);
1539 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1540 data_blob_free(&request);
1541 prs_mem_free(auth_data);
1542 return nt_status;
1545 /* Wrap this in SPNEGO. */
1546 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1548 data_blob_free(&request);
1550 /* Auth len in the rpc header doesn't include auth_header. */
1551 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1552 data_blob_free(&spnego_msg);
1553 prs_mem_free(auth_data);
1554 return NT_STATUS_NO_MEMORY;
1557 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1558 dump_data(5, spnego_msg.data, spnego_msg.length);
1560 data_blob_free(&spnego_msg);
1561 return NT_STATUS_OK;
1564 /*******************************************************************
1565 Creates NTLMSSP auth bind.
1566 ********************************************************************/
1568 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1569 enum pipe_auth_level auth_level,
1570 RPC_HDR_AUTH *pauth_out,
1571 prs_struct *auth_data)
1573 NTSTATUS nt_status;
1574 DATA_BLOB null_blob = data_blob_null;
1575 DATA_BLOB request = data_blob_null;
1577 /* We may change the pad length before marshalling. */
1578 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1580 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1581 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1582 null_blob,
1583 &request);
1585 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1586 data_blob_free(&request);
1587 prs_mem_free(auth_data);
1588 return nt_status;
1591 /* Auth len in the rpc header doesn't include auth_header. */
1592 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1593 data_blob_free(&request);
1594 prs_mem_free(auth_data);
1595 return NT_STATUS_NO_MEMORY;
1598 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1599 dump_data(5, request.data, request.length);
1601 data_blob_free(&request);
1602 return NT_STATUS_OK;
1605 /*******************************************************************
1606 Creates schannel auth bind.
1607 ********************************************************************/
1609 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1610 enum pipe_auth_level auth_level,
1611 RPC_HDR_AUTH *pauth_out,
1612 prs_struct *auth_data)
1614 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1616 /* We may change the pad length before marshalling. */
1617 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1619 /* Use lp_workgroup() if domain not specified */
1621 if (!cli->auth->domain || !cli->auth->domain[0]) {
1622 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1623 if (cli->auth->domain == NULL) {
1624 return NT_STATUS_NO_MEMORY;
1628 init_rpc_auth_schannel_neg(&schannel_neg, cli->auth->domain,
1629 global_myname());
1632 * Now marshall the data into the auth parse_struct.
1635 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1636 &schannel_neg, auth_data, 0)) {
1637 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1638 prs_mem_free(auth_data);
1639 return NT_STATUS_NO_MEMORY;
1642 return NT_STATUS_OK;
1645 /*******************************************************************
1646 Creates the internals of a DCE/RPC bind request or alter context PDU.
1647 ********************************************************************/
1649 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1650 prs_struct *rpc_out,
1651 uint32 rpc_call_id,
1652 const struct ndr_syntax_id *abstract,
1653 const struct ndr_syntax_id *transfer,
1654 RPC_HDR_AUTH *phdr_auth,
1655 prs_struct *pauth_info)
1657 RPC_HDR hdr;
1658 RPC_HDR_RB hdr_rb;
1659 RPC_CONTEXT rpc_ctx;
1660 uint16 auth_len = prs_offset(pauth_info);
1661 uint8 ss_padding_len = 0;
1662 uint16 frag_len = 0;
1664 /* create the RPC context. */
1665 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1667 /* create the bind request RPC_HDR_RB */
1668 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1670 /* Start building the frag length. */
1671 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1673 /* Do we need to pad ? */
1674 if (auth_len) {
1675 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1676 if (data_len % 8) {
1677 ss_padding_len = 8 - (data_len % 8);
1678 phdr_auth->auth_pad_len = ss_padding_len;
1680 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1683 /* Create the request RPC_HDR */
1684 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1686 /* Marshall the RPC header */
1687 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1688 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1689 return NT_STATUS_NO_MEMORY;
1692 /* Marshall the bind request data */
1693 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1694 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1695 return NT_STATUS_NO_MEMORY;
1699 * Grow the outgoing buffer to store any auth info.
1702 if(auth_len != 0) {
1703 if (ss_padding_len) {
1704 char pad[8];
1705 memset(pad, '\0', 8);
1706 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1707 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1708 return NT_STATUS_NO_MEMORY;
1712 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1713 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1714 return NT_STATUS_NO_MEMORY;
1718 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1719 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1720 return NT_STATUS_NO_MEMORY;
1724 return NT_STATUS_OK;
1727 /*******************************************************************
1728 Creates a DCE/RPC bind request.
1729 ********************************************************************/
1731 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1732 prs_struct *rpc_out,
1733 uint32 rpc_call_id,
1734 const struct ndr_syntax_id *abstract,
1735 const struct ndr_syntax_id *transfer,
1736 enum pipe_auth_type auth_type,
1737 enum pipe_auth_level auth_level)
1739 RPC_HDR_AUTH hdr_auth;
1740 prs_struct auth_info;
1741 NTSTATUS ret = NT_STATUS_OK;
1743 ZERO_STRUCT(hdr_auth);
1744 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1745 return NT_STATUS_NO_MEMORY;
1747 switch (auth_type) {
1748 case PIPE_AUTH_TYPE_SCHANNEL:
1749 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1750 if (!NT_STATUS_IS_OK(ret)) {
1751 prs_mem_free(&auth_info);
1752 return ret;
1754 break;
1756 case PIPE_AUTH_TYPE_NTLMSSP:
1757 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1758 if (!NT_STATUS_IS_OK(ret)) {
1759 prs_mem_free(&auth_info);
1760 return ret;
1762 break;
1764 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1765 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1766 if (!NT_STATUS_IS_OK(ret)) {
1767 prs_mem_free(&auth_info);
1768 return ret;
1770 break;
1772 case PIPE_AUTH_TYPE_KRB5:
1773 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1774 if (!NT_STATUS_IS_OK(ret)) {
1775 prs_mem_free(&auth_info);
1776 return ret;
1778 break;
1780 case PIPE_AUTH_TYPE_NONE:
1781 break;
1783 default:
1784 /* "Can't" happen. */
1785 return NT_STATUS_INVALID_INFO_CLASS;
1788 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1789 rpc_out,
1790 rpc_call_id,
1791 abstract,
1792 transfer,
1793 &hdr_auth,
1794 &auth_info);
1796 prs_mem_free(&auth_info);
1797 return ret;
1800 /*******************************************************************
1801 Create and add the NTLMSSP sign/seal auth header and data.
1802 ********************************************************************/
1804 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1805 RPC_HDR *phdr,
1806 uint32 ss_padding_len,
1807 prs_struct *outgoing_pdu)
1809 RPC_HDR_AUTH auth_info;
1810 NTSTATUS status;
1811 DATA_BLOB auth_blob = data_blob_null;
1812 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1814 if (!cli->auth->a_u.ntlmssp_state) {
1815 return NT_STATUS_INVALID_PARAMETER;
1818 /* Init and marshall the auth header. */
1819 init_rpc_hdr_auth(&auth_info,
1820 map_pipe_auth_type_to_rpc_auth_type(
1821 cli->auth->auth_type),
1822 cli->auth->auth_level,
1823 ss_padding_len,
1824 1 /* context id. */);
1826 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1827 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1828 data_blob_free(&auth_blob);
1829 return NT_STATUS_NO_MEMORY;
1832 switch (cli->auth->auth_level) {
1833 case PIPE_AUTH_LEVEL_PRIVACY:
1834 /* Data portion is encrypted. */
1835 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1836 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1837 data_and_pad_len,
1838 (unsigned char *)prs_data_p(outgoing_pdu),
1839 (size_t)prs_offset(outgoing_pdu),
1840 &auth_blob);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 data_blob_free(&auth_blob);
1843 return status;
1845 break;
1847 case PIPE_AUTH_LEVEL_INTEGRITY:
1848 /* Data is signed. */
1849 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1850 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1851 data_and_pad_len,
1852 (unsigned char *)prs_data_p(outgoing_pdu),
1853 (size_t)prs_offset(outgoing_pdu),
1854 &auth_blob);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 data_blob_free(&auth_blob);
1857 return status;
1859 break;
1861 default:
1862 /* Can't happen. */
1863 smb_panic("bad auth level");
1864 /* Notreached. */
1865 return NT_STATUS_INVALID_PARAMETER;
1868 /* Finally marshall the blob. */
1870 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1871 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1872 (unsigned int)NTLMSSP_SIG_SIZE));
1873 data_blob_free(&auth_blob);
1874 return NT_STATUS_NO_MEMORY;
1877 data_blob_free(&auth_blob);
1878 return NT_STATUS_OK;
1881 /*******************************************************************
1882 Create and add the schannel sign/seal auth header and data.
1883 ********************************************************************/
1885 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1886 RPC_HDR *phdr,
1887 uint32 ss_padding_len,
1888 prs_struct *outgoing_pdu)
1890 RPC_HDR_AUTH auth_info;
1891 RPC_AUTH_SCHANNEL_CHK verf;
1892 struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
1893 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1894 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1896 if (!sas) {
1897 return NT_STATUS_INVALID_PARAMETER;
1900 /* Init and marshall the auth header. */
1901 init_rpc_hdr_auth(&auth_info,
1902 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1903 cli->auth->auth_level,
1904 ss_padding_len,
1905 1 /* context id. */);
1907 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1908 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1909 return NT_STATUS_NO_MEMORY;
1912 switch (cli->auth->auth_level) {
1913 case PIPE_AUTH_LEVEL_PRIVACY:
1914 case PIPE_AUTH_LEVEL_INTEGRITY:
1915 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1916 sas->seq_num));
1918 schannel_encode(sas,
1919 cli->auth->auth_level,
1920 SENDER_IS_INITIATOR,
1921 &verf,
1922 data_p,
1923 data_and_pad_len);
1925 sas->seq_num++;
1926 break;
1928 default:
1929 /* Can't happen. */
1930 smb_panic("bad auth level");
1931 /* Notreached. */
1932 return NT_STATUS_INVALID_PARAMETER;
1935 /* Finally marshall the blob. */
1936 smb_io_rpc_auth_schannel_chk("",
1937 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1938 &verf,
1939 outgoing_pdu,
1942 return NT_STATUS_OK;
1945 /*******************************************************************
1946 Calculate how much data we're going to send in this packet, also
1947 work out any sign/seal padding length.
1948 ********************************************************************/
1950 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1951 uint32 data_left,
1952 uint16 *p_frag_len,
1953 uint16 *p_auth_len,
1954 uint32 *p_ss_padding)
1956 uint32 data_space, data_len;
1958 #ifdef DEVELOPER
1959 if ((data_left > 0) && (sys_random() % 2)) {
1960 data_left = MAX(data_left/2, 1);
1962 #endif
1964 switch (cli->auth->auth_level) {
1965 case PIPE_AUTH_LEVEL_NONE:
1966 case PIPE_AUTH_LEVEL_CONNECT:
1967 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1968 data_len = MIN(data_space, data_left);
1969 *p_ss_padding = 0;
1970 *p_auth_len = 0;
1971 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1972 return data_len;
1974 case PIPE_AUTH_LEVEL_INTEGRITY:
1975 case PIPE_AUTH_LEVEL_PRIVACY:
1976 /* Treat the same for all authenticated rpc requests. */
1977 switch(cli->auth->auth_type) {
1978 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1979 case PIPE_AUTH_TYPE_NTLMSSP:
1980 *p_auth_len = NTLMSSP_SIG_SIZE;
1981 break;
1982 case PIPE_AUTH_TYPE_SCHANNEL:
1983 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1984 break;
1985 default:
1986 smb_panic("bad auth type");
1987 break;
1990 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1991 RPC_HDR_AUTH_LEN - *p_auth_len;
1993 data_len = MIN(data_space, data_left);
1994 *p_ss_padding = 0;
1995 if (data_len % 8) {
1996 *p_ss_padding = 8 - (data_len % 8);
1998 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1999 data_len + *p_ss_padding + /* data plus padding. */
2000 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
2001 return data_len;
2003 default:
2004 smb_panic("bad auth level");
2005 /* Notreached. */
2006 return 0;
2010 /*******************************************************************
2011 External interface.
2012 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2013 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2014 and deals with signing/sealing details.
2015 ********************************************************************/
2017 struct rpc_api_pipe_req_state {
2018 struct event_context *ev;
2019 struct rpc_pipe_client *cli;
2020 uint8_t op_num;
2021 uint32_t call_id;
2022 prs_struct *req_data;
2023 uint32_t req_data_sent;
2024 prs_struct outgoing_frag;
2025 prs_struct reply_pdu;
2028 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2030 prs_mem_free(&s->outgoing_frag);
2031 prs_mem_free(&s->reply_pdu);
2032 return 0;
2035 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2036 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2037 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2038 bool *is_last_frag);
2040 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2041 struct event_context *ev,
2042 struct rpc_pipe_client *cli,
2043 uint8_t op_num,
2044 prs_struct *req_data)
2046 struct tevent_req *req, *subreq;
2047 struct rpc_api_pipe_req_state *state;
2048 NTSTATUS status;
2049 bool is_last_frag;
2051 req = tevent_req_create(mem_ctx, &state,
2052 struct rpc_api_pipe_req_state);
2053 if (req == NULL) {
2054 return NULL;
2056 state->ev = ev;
2057 state->cli = cli;
2058 state->op_num = op_num;
2059 state->req_data = req_data;
2060 state->req_data_sent = 0;
2061 state->call_id = get_rpc_call_id();
2063 if (cli->max_xmit_frag
2064 < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2065 /* Server is screwed up ! */
2066 status = NT_STATUS_INVALID_PARAMETER;
2067 goto post_status;
2070 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2072 if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2073 state, MARSHALL)) {
2074 goto fail;
2077 talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2079 status = prepare_next_frag(state, &is_last_frag);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 goto post_status;
2084 if (is_last_frag) {
2085 subreq = rpc_api_pipe_send(state, ev, state->cli,
2086 &state->outgoing_frag,
2087 RPC_RESPONSE);
2088 if (subreq == NULL) {
2089 goto fail;
2091 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2092 } else {
2093 subreq = rpc_write_send(
2094 state, ev, cli->transport,
2095 (uint8_t *)prs_data_p(&state->outgoing_frag),
2096 prs_offset(&state->outgoing_frag));
2097 if (subreq == NULL) {
2098 goto fail;
2100 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2101 req);
2103 return req;
2105 post_status:
2106 tevent_req_nterror(req, status);
2107 return tevent_req_post(req, ev);
2108 fail:
2109 TALLOC_FREE(req);
2110 return NULL;
2113 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2114 bool *is_last_frag)
2116 RPC_HDR hdr;
2117 RPC_HDR_REQ hdr_req;
2118 uint32_t data_sent_thistime;
2119 uint16_t auth_len;
2120 uint16_t frag_len;
2121 uint8_t flags = 0;
2122 uint32_t ss_padding;
2123 uint32_t data_left;
2124 char pad[8] = { 0, };
2125 NTSTATUS status;
2127 data_left = prs_offset(state->req_data) - state->req_data_sent;
2129 data_sent_thistime = calculate_data_len_tosend(
2130 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2132 if (state->req_data_sent == 0) {
2133 flags = RPC_FLG_FIRST;
2136 if (data_sent_thistime == data_left) {
2137 flags |= RPC_FLG_LAST;
2140 if (!prs_set_offset(&state->outgoing_frag, 0)) {
2141 return NT_STATUS_NO_MEMORY;
2144 /* Create and marshall the header and request header. */
2145 init_rpc_hdr(&hdr, RPC_REQUEST, flags, state->call_id, frag_len,
2146 auth_len);
2148 if (!smb_io_rpc_hdr("hdr ", &hdr, &state->outgoing_frag, 0)) {
2149 return NT_STATUS_NO_MEMORY;
2152 /* Create the rpc request RPC_HDR_REQ */
2153 init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2154 state->op_num);
2156 if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2157 &state->outgoing_frag, 0)) {
2158 return NT_STATUS_NO_MEMORY;
2161 /* Copy in the data, plus any ss padding. */
2162 if (!prs_append_some_prs_data(&state->outgoing_frag,
2163 state->req_data, state->req_data_sent,
2164 data_sent_thistime)) {
2165 return NT_STATUS_NO_MEMORY;
2168 /* Copy the sign/seal padding data. */
2169 if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2170 return NT_STATUS_NO_MEMORY;
2173 /* Generate any auth sign/seal and add the auth footer. */
2174 switch (state->cli->auth->auth_type) {
2175 case PIPE_AUTH_TYPE_NONE:
2176 status = NT_STATUS_OK;
2177 break;
2178 case PIPE_AUTH_TYPE_NTLMSSP:
2179 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2180 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2181 &state->outgoing_frag);
2182 break;
2183 case PIPE_AUTH_TYPE_SCHANNEL:
2184 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2185 &state->outgoing_frag);
2186 break;
2187 default:
2188 status = NT_STATUS_INVALID_PARAMETER;
2189 break;
2192 state->req_data_sent += data_sent_thistime;
2193 *is_last_frag = ((flags & RPC_FLG_LAST) != 0);
2195 return status;
2198 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2200 struct tevent_req *req = tevent_req_callback_data(
2201 subreq, struct tevent_req);
2202 struct rpc_api_pipe_req_state *state = tevent_req_data(
2203 req, struct rpc_api_pipe_req_state);
2204 NTSTATUS status;
2205 bool is_last_frag;
2207 status = rpc_write_recv(subreq);
2208 TALLOC_FREE(subreq);
2209 if (!NT_STATUS_IS_OK(status)) {
2210 tevent_req_nterror(req, status);
2211 return;
2214 status = prepare_next_frag(state, &is_last_frag);
2215 if (!NT_STATUS_IS_OK(status)) {
2216 tevent_req_nterror(req, status);
2217 return;
2220 if (is_last_frag) {
2221 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2222 &state->outgoing_frag,
2223 RPC_RESPONSE);
2224 if (tevent_req_nomem(subreq, req)) {
2225 return;
2227 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2228 } else {
2229 subreq = rpc_write_send(
2230 state, state->ev,
2231 state->cli->transport,
2232 (uint8_t *)prs_data_p(&state->outgoing_frag),
2233 prs_offset(&state->outgoing_frag));
2234 if (tevent_req_nomem(subreq, req)) {
2235 return;
2237 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2238 req);
2242 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2244 struct tevent_req *req = tevent_req_callback_data(
2245 subreq, struct tevent_req);
2246 struct rpc_api_pipe_req_state *state = tevent_req_data(
2247 req, struct rpc_api_pipe_req_state);
2248 NTSTATUS status;
2250 status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2251 TALLOC_FREE(subreq);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 tevent_req_nterror(req, status);
2254 return;
2256 tevent_req_done(req);
2259 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2260 prs_struct *reply_pdu)
2262 struct rpc_api_pipe_req_state *state = tevent_req_data(
2263 req, struct rpc_api_pipe_req_state);
2264 NTSTATUS status;
2266 if (tevent_req_is_nterror(req, &status)) {
2268 * We always have to initialize to reply pdu, even if there is
2269 * none. The rpccli_* caller routines expect this.
2271 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2272 return status;
2275 *reply_pdu = state->reply_pdu;
2276 reply_pdu->mem_ctx = mem_ctx;
2279 * Prevent state->req_pdu from being freed in
2280 * rpc_api_pipe_req_state_destructor()
2282 prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2284 return NT_STATUS_OK;
2287 #if 0
2288 /****************************************************************************
2289 Set the handle state.
2290 ****************************************************************************/
2292 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2293 const char *pipe_name, uint16 device_state)
2295 bool state_set = False;
2296 char param[2];
2297 uint16 setup[2]; /* only need 2 uint16 setup parameters */
2298 char *rparam = NULL;
2299 char *rdata = NULL;
2300 uint32 rparam_len, rdata_len;
2302 if (pipe_name == NULL)
2303 return False;
2305 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2306 cli->fnum, pipe_name, device_state));
2308 /* create parameters: device state */
2309 SSVAL(param, 0, device_state);
2311 /* create setup parameters. */
2312 setup[0] = 0x0001;
2313 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
2315 /* send the data on \PIPE\ */
2316 if (cli_api_pipe(cli->cli, "\\PIPE\\",
2317 setup, 2, 0, /* setup, length, max */
2318 param, 2, 0, /* param, length, max */
2319 NULL, 0, 1024, /* data, length, max */
2320 &rparam, &rparam_len, /* return param, length */
2321 &rdata, &rdata_len)) /* return data, length */
2323 DEBUG(5, ("Set Handle state: return OK\n"));
2324 state_set = True;
2327 SAFE_FREE(rparam);
2328 SAFE_FREE(rdata);
2330 return state_set;
2332 #endif
2334 /****************************************************************************
2335 Check the rpc bind acknowledge response.
2336 ****************************************************************************/
2338 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2339 const struct ndr_syntax_id *transfer)
2341 if ( hdr_ba->addr.len == 0) {
2342 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2345 /* check the transfer syntax */
2346 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2347 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2348 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2349 return False;
2352 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2353 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2354 hdr_ba->res.num_results, hdr_ba->res.reason));
2357 DEBUG(5,("check_bind_response: accepted!\n"));
2358 return True;
2361 /*******************************************************************
2362 Creates a DCE/RPC bind authentication response.
2363 This is the packet that is sent back to the server once we
2364 have received a BIND-ACK, to finish the third leg of
2365 the authentication handshake.
2366 ********************************************************************/
2368 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2369 uint32 rpc_call_id,
2370 enum pipe_auth_type auth_type,
2371 enum pipe_auth_level auth_level,
2372 DATA_BLOB *pauth_blob,
2373 prs_struct *rpc_out)
2375 RPC_HDR hdr;
2376 RPC_HDR_AUTH hdr_auth;
2377 uint32 pad = 0;
2379 /* Create the request RPC_HDR */
2380 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
2381 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2382 pauth_blob->length );
2384 /* Marshall it. */
2385 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2386 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2387 return NT_STATUS_NO_MEMORY;
2391 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2392 about padding - shouldn't this pad to length 8 ? JRA.
2395 /* 4 bytes padding. */
2396 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2397 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2398 return NT_STATUS_NO_MEMORY;
2401 /* Create the request RPC_HDR_AUTHA */
2402 init_rpc_hdr_auth(&hdr_auth,
2403 map_pipe_auth_type_to_rpc_auth_type(auth_type),
2404 auth_level, 0, 1);
2406 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2407 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2408 return NT_STATUS_NO_MEMORY;
2412 * Append the auth data to the outgoing buffer.
2415 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2416 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2417 return NT_STATUS_NO_MEMORY;
2420 return NT_STATUS_OK;
2423 /*******************************************************************
2424 Creates a DCE/RPC bind alter context authentication request which
2425 may contain a spnego auth blobl
2426 ********************************************************************/
2428 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2429 const struct ndr_syntax_id *abstract,
2430 const struct ndr_syntax_id *transfer,
2431 enum pipe_auth_level auth_level,
2432 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2433 prs_struct *rpc_out)
2435 RPC_HDR_AUTH hdr_auth;
2436 prs_struct auth_info;
2437 NTSTATUS ret = NT_STATUS_OK;
2439 ZERO_STRUCT(hdr_auth);
2440 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2441 return NT_STATUS_NO_MEMORY;
2443 /* We may change the pad length before marshalling. */
2444 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
2446 if (pauth_blob->length) {
2447 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2448 prs_mem_free(&auth_info);
2449 return NT_STATUS_NO_MEMORY;
2453 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
2454 rpc_out,
2455 rpc_call_id,
2456 abstract,
2457 transfer,
2458 &hdr_auth,
2459 &auth_info);
2460 prs_mem_free(&auth_info);
2461 return ret;
2464 /****************************************************************************
2465 Do an rpc bind.
2466 ****************************************************************************/
2468 struct rpc_pipe_bind_state {
2469 struct event_context *ev;
2470 struct rpc_pipe_client *cli;
2471 prs_struct rpc_out;
2472 uint32_t rpc_call_id;
2475 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2477 prs_mem_free(&state->rpc_out);
2478 return 0;
2481 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2482 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2483 struct rpc_pipe_bind_state *state,
2484 struct rpc_hdr_info *phdr,
2485 prs_struct *reply_pdu);
2486 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2487 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2488 struct rpc_pipe_bind_state *state,
2489 struct rpc_hdr_info *phdr,
2490 prs_struct *reply_pdu);
2491 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2493 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2494 struct event_context *ev,
2495 struct rpc_pipe_client *cli,
2496 struct cli_pipe_auth_data *auth)
2498 struct tevent_req *req, *subreq;
2499 struct rpc_pipe_bind_state *state;
2500 NTSTATUS status;
2502 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2503 if (req == NULL) {
2504 return NULL;
2507 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2508 rpccli_pipe_txt(debug_ctx(), cli),
2509 (unsigned int)auth->auth_type,
2510 (unsigned int)auth->auth_level ));
2512 state->ev = ev;
2513 state->cli = cli;
2514 state->rpc_call_id = get_rpc_call_id();
2516 prs_init_empty(&state->rpc_out, state, MARSHALL);
2517 talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2519 cli->auth = talloc_move(cli, &auth);
2521 /* Marshall the outgoing data. */
2522 status = create_rpc_bind_req(cli, &state->rpc_out,
2523 state->rpc_call_id,
2524 &cli->abstract_syntax,
2525 &cli->transfer_syntax,
2526 cli->auth->auth_type,
2527 cli->auth->auth_level);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 goto post_status;
2533 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2534 RPC_BINDACK);
2535 if (subreq == NULL) {
2536 goto fail;
2538 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2539 return req;
2541 post_status:
2542 tevent_req_nterror(req, status);
2543 return tevent_req_post(req, ev);
2544 fail:
2545 TALLOC_FREE(req);
2546 return NULL;
2549 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2551 struct tevent_req *req = tevent_req_callback_data(
2552 subreq, struct tevent_req);
2553 struct rpc_pipe_bind_state *state = tevent_req_data(
2554 req, struct rpc_pipe_bind_state);
2555 prs_struct reply_pdu;
2556 struct rpc_hdr_info hdr;
2557 struct rpc_hdr_ba_info hdr_ba;
2558 NTSTATUS status;
2560 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2561 TALLOC_FREE(subreq);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2564 rpccli_pipe_txt(debug_ctx(), state->cli),
2565 nt_errstr(status)));
2566 tevent_req_nterror(req, status);
2567 return;
2570 /* Unmarshall the RPC header */
2571 if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2572 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2573 prs_mem_free(&reply_pdu);
2574 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2575 return;
2578 if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2579 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2580 "RPC_HDR_BA.\n"));
2581 prs_mem_free(&reply_pdu);
2582 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2583 return;
2586 if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2587 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2588 prs_mem_free(&reply_pdu);
2589 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2590 return;
2593 state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2594 state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2597 * For authenticated binds we may need to do 3 or 4 leg binds.
2600 switch(state->cli->auth->auth_type) {
2602 case PIPE_AUTH_TYPE_NONE:
2603 case PIPE_AUTH_TYPE_SCHANNEL:
2604 /* Bind complete. */
2605 prs_mem_free(&reply_pdu);
2606 tevent_req_done(req);
2607 break;
2609 case PIPE_AUTH_TYPE_NTLMSSP:
2610 /* Need to send AUTH3 packet - no reply. */
2611 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2612 &reply_pdu);
2613 prs_mem_free(&reply_pdu);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 tevent_req_nterror(req, status);
2617 break;
2619 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2620 /* Need to send alter context request and reply. */
2621 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2622 &reply_pdu);
2623 prs_mem_free(&reply_pdu);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 tevent_req_nterror(req, status);
2627 break;
2629 case PIPE_AUTH_TYPE_KRB5:
2630 /* */
2632 default:
2633 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2634 (unsigned int)state->cli->auth->auth_type));
2635 prs_mem_free(&reply_pdu);
2636 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2640 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2641 struct rpc_pipe_bind_state *state,
2642 struct rpc_hdr_info *phdr,
2643 prs_struct *reply_pdu)
2645 DATA_BLOB server_response = data_blob_null;
2646 DATA_BLOB client_reply = data_blob_null;
2647 struct rpc_hdr_auth_info hdr_auth;
2648 struct tevent_req *subreq;
2649 NTSTATUS status;
2651 if ((phdr->auth_len == 0)
2652 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2653 return NT_STATUS_INVALID_PARAMETER;
2656 if (!prs_set_offset(
2657 reply_pdu,
2658 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2659 return NT_STATUS_INVALID_PARAMETER;
2662 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2663 return NT_STATUS_INVALID_PARAMETER;
2666 /* TODO - check auth_type/auth_level match. */
2668 server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2669 prs_copy_data_out((char *)server_response.data, reply_pdu,
2670 phdr->auth_len);
2672 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2673 server_response, &client_reply);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2677 "blob failed: %s.\n", nt_errstr(status)));
2678 return status;
2681 prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2683 status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2684 state->cli->auth->auth_type,
2685 state->cli->auth->auth_level,
2686 &client_reply, &state->rpc_out);
2687 data_blob_free(&client_reply);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 return status;
2693 subreq = rpc_write_send(state, state->ev, state->cli->transport,
2694 (uint8_t *)prs_data_p(&state->rpc_out),
2695 prs_offset(&state->rpc_out));
2696 if (subreq == NULL) {
2697 return NT_STATUS_NO_MEMORY;
2699 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2700 return NT_STATUS_OK;
2703 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2705 struct tevent_req *req = tevent_req_callback_data(
2706 subreq, struct tevent_req);
2707 NTSTATUS status;
2709 status = rpc_write_recv(subreq);
2710 TALLOC_FREE(subreq);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 tevent_req_nterror(req, status);
2713 return;
2715 tevent_req_done(req);
2718 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2719 struct rpc_pipe_bind_state *state,
2720 struct rpc_hdr_info *phdr,
2721 prs_struct *reply_pdu)
2723 DATA_BLOB server_spnego_response = data_blob_null;
2724 DATA_BLOB server_ntlm_response = data_blob_null;
2725 DATA_BLOB client_reply = data_blob_null;
2726 DATA_BLOB tmp_blob = data_blob_null;
2727 RPC_HDR_AUTH hdr_auth;
2728 struct tevent_req *subreq;
2729 NTSTATUS status;
2731 if ((phdr->auth_len == 0)
2732 || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2733 return NT_STATUS_INVALID_PARAMETER;
2736 /* Process the returned NTLMSSP blob first. */
2737 if (!prs_set_offset(
2738 reply_pdu,
2739 phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2740 return NT_STATUS_INVALID_PARAMETER;
2743 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2744 return NT_STATUS_INVALID_PARAMETER;
2747 server_spnego_response = data_blob(NULL, phdr->auth_len);
2748 prs_copy_data_out((char *)server_spnego_response.data,
2749 reply_pdu, phdr->auth_len);
2752 * The server might give us back two challenges - tmp_blob is for the
2753 * second.
2755 if (!spnego_parse_challenge(server_spnego_response,
2756 &server_ntlm_response, &tmp_blob)) {
2757 data_blob_free(&server_spnego_response);
2758 data_blob_free(&server_ntlm_response);
2759 data_blob_free(&tmp_blob);
2760 return NT_STATUS_INVALID_PARAMETER;
2763 /* We're finished with the server spnego response and the tmp_blob. */
2764 data_blob_free(&server_spnego_response);
2765 data_blob_free(&tmp_blob);
2767 status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2768 server_ntlm_response, &client_reply);
2770 /* Finished with the server_ntlm response */
2771 data_blob_free(&server_ntlm_response);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2775 "using server blob failed.\n"));
2776 data_blob_free(&client_reply);
2777 return status;
2780 /* SPNEGO wrap the client reply. */
2781 tmp_blob = spnego_gen_auth(client_reply);
2782 data_blob_free(&client_reply);
2783 client_reply = tmp_blob;
2784 tmp_blob = data_blob_null;
2786 /* Now prepare the alter context pdu. */
2787 prs_init_empty(&state->rpc_out, state, MARSHALL);
2789 status = create_rpc_alter_context(state->rpc_call_id,
2790 &state->cli->abstract_syntax,
2791 &state->cli->transfer_syntax,
2792 state->cli->auth->auth_level,
2793 &client_reply,
2794 &state->rpc_out);
2795 data_blob_free(&client_reply);
2797 if (!NT_STATUS_IS_OK(status)) {
2798 return status;
2801 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2802 &state->rpc_out, RPC_ALTCONTRESP);
2803 if (subreq == NULL) {
2804 return NT_STATUS_NO_MEMORY;
2806 tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2807 return NT_STATUS_OK;
2810 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2812 struct tevent_req *req = tevent_req_callback_data(
2813 subreq, struct tevent_req);
2814 struct rpc_pipe_bind_state *state = tevent_req_data(
2815 req, struct rpc_pipe_bind_state);
2816 DATA_BLOB server_spnego_response = data_blob_null;
2817 DATA_BLOB tmp_blob = data_blob_null;
2818 prs_struct reply_pdu;
2819 struct rpc_hdr_info hdr;
2820 struct rpc_hdr_auth_info hdr_auth;
2821 NTSTATUS status;
2823 status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2824 TALLOC_FREE(subreq);
2825 if (!NT_STATUS_IS_OK(status)) {
2826 tevent_req_nterror(req, status);
2827 return;
2830 /* Get the auth blob from the reply. */
2831 if (!smb_io_rpc_hdr("rpc_hdr ", &hdr, &reply_pdu, 0)) {
2832 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
2833 "unmarshall RPC_HDR.\n"));
2834 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2835 return;
2838 if (!prs_set_offset(
2839 &reply_pdu,
2840 hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
2841 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2842 return;
2845 if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
2846 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2847 return;
2850 server_spnego_response = data_blob(NULL, hdr.auth_len);
2851 prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
2852 hdr.auth_len);
2854 /* Check we got a valid auth response. */
2855 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
2856 OID_NTLMSSP, &tmp_blob)) {
2857 data_blob_free(&server_spnego_response);
2858 data_blob_free(&tmp_blob);
2859 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2860 return;
2863 data_blob_free(&server_spnego_response);
2864 data_blob_free(&tmp_blob);
2866 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2867 "%s.\n", rpccli_pipe_txt(debug_ctx(), state->cli)));
2868 tevent_req_done(req);
2871 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2873 return tevent_req_simple_recv_ntstatus(req);
2876 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2877 struct cli_pipe_auth_data *auth)
2879 TALLOC_CTX *frame = talloc_stackframe();
2880 struct event_context *ev;
2881 struct tevent_req *req;
2882 NTSTATUS status = NT_STATUS_OK;
2884 ev = event_context_init(frame);
2885 if (ev == NULL) {
2886 status = NT_STATUS_NO_MEMORY;
2887 goto fail;
2890 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2891 if (req == NULL) {
2892 status = NT_STATUS_NO_MEMORY;
2893 goto fail;
2896 if (!tevent_req_poll(req, ev)) {
2897 status = map_nt_error_from_unix(errno);
2898 goto fail;
2901 status = rpc_pipe_bind_recv(req);
2902 fail:
2903 TALLOC_FREE(frame);
2904 return status;
2907 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2908 unsigned int timeout)
2910 struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
2912 if (cli == NULL) {
2913 return 0;
2915 return cli_set_timeout(cli, timeout);
2918 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2920 struct cli_state *cli;
2922 if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2923 || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2924 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2925 return true;
2928 cli = rpc_pipe_np_smb_conn(rpc_cli);
2929 if (cli == NULL) {
2930 return false;
2932 E_md4hash(cli->password ? cli->password : "", nt_hash);
2933 return true;
2936 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2937 struct cli_pipe_auth_data **presult)
2939 struct cli_pipe_auth_data *result;
2941 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2942 if (result == NULL) {
2943 return NT_STATUS_NO_MEMORY;
2946 result->auth_type = PIPE_AUTH_TYPE_NONE;
2947 result->auth_level = PIPE_AUTH_LEVEL_NONE;
2949 result->user_name = talloc_strdup(result, "");
2950 result->domain = talloc_strdup(result, "");
2951 if ((result->user_name == NULL) || (result->domain == NULL)) {
2952 TALLOC_FREE(result);
2953 return NT_STATUS_NO_MEMORY;
2956 *presult = result;
2957 return NT_STATUS_OK;
2960 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2962 ntlmssp_end(&auth->a_u.ntlmssp_state);
2963 return 0;
2966 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2967 enum pipe_auth_type auth_type,
2968 enum pipe_auth_level auth_level,
2969 const char *domain,
2970 const char *username,
2971 const char *password,
2972 struct cli_pipe_auth_data **presult)
2974 struct cli_pipe_auth_data *result;
2975 NTSTATUS status;
2977 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2978 if (result == NULL) {
2979 return NT_STATUS_NO_MEMORY;
2982 result->auth_type = auth_type;
2983 result->auth_level = auth_level;
2985 result->user_name = talloc_strdup(result, username);
2986 result->domain = talloc_strdup(result, domain);
2987 if ((result->user_name == NULL) || (result->domain == NULL)) {
2988 status = NT_STATUS_NO_MEMORY;
2989 goto fail;
2992 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
2993 if (!NT_STATUS_IS_OK(status)) {
2994 goto fail;
2997 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2999 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3000 if (!NT_STATUS_IS_OK(status)) {
3001 goto fail;
3004 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3005 if (!NT_STATUS_IS_OK(status)) {
3006 goto fail;
3009 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3010 if (!NT_STATUS_IS_OK(status)) {
3011 goto fail;
3015 * Turn off sign+seal to allow selected auth level to turn it back on.
3017 result->a_u.ntlmssp_state->neg_flags &=
3018 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3020 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
3021 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3022 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
3023 result->a_u.ntlmssp_state->neg_flags
3024 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3027 *presult = result;
3028 return NT_STATUS_OK;
3030 fail:
3031 TALLOC_FREE(result);
3032 return status;
3035 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3036 enum pipe_auth_level auth_level,
3037 const uint8_t sess_key[16],
3038 struct cli_pipe_auth_data **presult)
3040 struct cli_pipe_auth_data *result;
3042 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3043 if (result == NULL) {
3044 return NT_STATUS_NO_MEMORY;
3047 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3048 result->auth_level = auth_level;
3050 result->user_name = talloc_strdup(result, "");
3051 result->domain = talloc_strdup(result, domain);
3052 if ((result->user_name == NULL) || (result->domain == NULL)) {
3053 goto fail;
3056 result->a_u.schannel_auth = talloc(result,
3057 struct schannel_auth_struct);
3058 if (result->a_u.schannel_auth == NULL) {
3059 goto fail;
3062 memcpy(result->a_u.schannel_auth->sess_key, sess_key,
3063 sizeof(result->a_u.schannel_auth->sess_key));
3064 result->a_u.schannel_auth->seq_num = 0;
3066 *presult = result;
3067 return NT_STATUS_OK;
3069 fail:
3070 TALLOC_FREE(result);
3071 return NT_STATUS_NO_MEMORY;
3074 #ifdef HAVE_KRB5
3075 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3077 data_blob_free(&auth->session_key);
3078 return 0;
3080 #endif
3082 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3083 enum pipe_auth_level auth_level,
3084 const char *service_princ,
3085 const char *username,
3086 const char *password,
3087 struct cli_pipe_auth_data **presult)
3089 #ifdef HAVE_KRB5
3090 struct cli_pipe_auth_data *result;
3092 if ((username != NULL) && (password != NULL)) {
3093 int ret = kerberos_kinit_password(username, password, 0, NULL);
3094 if (ret != 0) {
3095 return NT_STATUS_ACCESS_DENIED;
3099 result = talloc(mem_ctx, struct cli_pipe_auth_data);
3100 if (result == NULL) {
3101 return NT_STATUS_NO_MEMORY;
3104 result->auth_type = PIPE_AUTH_TYPE_KRB5;
3105 result->auth_level = auth_level;
3108 * Username / domain need fixing!
3110 result->user_name = talloc_strdup(result, "");
3111 result->domain = talloc_strdup(result, "");
3112 if ((result->user_name == NULL) || (result->domain == NULL)) {
3113 goto fail;
3116 result->a_u.kerberos_auth = TALLOC_ZERO_P(
3117 result, struct kerberos_auth_struct);
3118 if (result->a_u.kerberos_auth == NULL) {
3119 goto fail;
3121 talloc_set_destructor(result->a_u.kerberos_auth,
3122 cli_auth_kerberos_data_destructor);
3124 result->a_u.kerberos_auth->service_principal = talloc_strdup(
3125 result, service_princ);
3126 if (result->a_u.kerberos_auth->service_principal == NULL) {
3127 goto fail;
3130 *presult = result;
3131 return NT_STATUS_OK;
3133 fail:
3134 TALLOC_FREE(result);
3135 return NT_STATUS_NO_MEMORY;
3136 #else
3137 return NT_STATUS_NOT_SUPPORTED;
3138 #endif
3142 * Create an rpc pipe client struct, connecting to a tcp port.
3144 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3145 uint16_t port,
3146 const struct ndr_syntax_id *abstract_syntax,
3147 struct rpc_pipe_client **presult)
3149 struct rpc_pipe_client *result;
3150 struct sockaddr_storage addr;
3151 NTSTATUS status;
3152 int fd;
3154 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3155 if (result == NULL) {
3156 return NT_STATUS_NO_MEMORY;
3159 result->abstract_syntax = *abstract_syntax;
3160 result->transfer_syntax = ndr_transfer_syntax;
3161 result->dispatch = cli_do_rpc_ndr;
3162 result->dispatch_send = cli_do_rpc_ndr_send;
3163 result->dispatch_recv = cli_do_rpc_ndr_recv;
3165 result->desthost = talloc_strdup(result, host);
3166 result->srv_name_slash = talloc_asprintf_strupper_m(
3167 result, "\\\\%s", result->desthost);
3168 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3169 status = NT_STATUS_NO_MEMORY;
3170 goto fail;
3173 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3174 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3176 if (!resolve_name(host, &addr, 0, false)) {
3177 status = NT_STATUS_NOT_FOUND;
3178 goto fail;
3181 status = open_socket_out(&addr, port, 60, &fd);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 goto fail;
3185 set_socket_options(fd, lp_socket_options());
3187 status = rpc_transport_sock_init(result, fd, &result->transport);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 close(fd);
3190 goto fail;
3193 *presult = result;
3194 return NT_STATUS_OK;
3196 fail:
3197 TALLOC_FREE(result);
3198 return status;
3202 * Determine the tcp port on which a dcerpc interface is listening
3203 * for the ncacn_ip_tcp transport via the endpoint mapper of the
3204 * target host.
3206 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3207 const struct ndr_syntax_id *abstract_syntax,
3208 uint16_t *pport)
3210 NTSTATUS status;
3211 struct rpc_pipe_client *epm_pipe = NULL;
3212 struct cli_pipe_auth_data *auth = NULL;
3213 struct dcerpc_binding *map_binding = NULL;
3214 struct dcerpc_binding *res_binding = NULL;
3215 struct epm_twr_t *map_tower = NULL;
3216 struct epm_twr_t *res_towers = NULL;
3217 struct policy_handle *entry_handle = NULL;
3218 uint32_t num_towers = 0;
3219 uint32_t max_towers = 1;
3220 struct epm_twr_p_t towers;
3221 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3223 if (pport == NULL) {
3224 status = NT_STATUS_INVALID_PARAMETER;
3225 goto done;
3228 /* open the connection to the endpoint mapper */
3229 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3230 &ndr_table_epmapper.syntax_id,
3231 &epm_pipe);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 goto done;
3237 status = rpccli_anon_bind_data(tmp_ctx, &auth);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 goto done;
3242 status = rpc_pipe_bind(epm_pipe, auth);
3243 if (!NT_STATUS_IS_OK(status)) {
3244 goto done;
3247 /* create tower for asking the epmapper */
3249 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3250 if (map_binding == NULL) {
3251 status = NT_STATUS_NO_MEMORY;
3252 goto done;
3255 map_binding->transport = NCACN_IP_TCP;
3256 map_binding->object = *abstract_syntax;
3257 map_binding->host = host; /* needed? */
3258 map_binding->endpoint = "0"; /* correct? needed? */
3260 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3261 if (map_tower == NULL) {
3262 status = NT_STATUS_NO_MEMORY;
3263 goto done;
3266 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3267 &(map_tower->tower));
3268 if (!NT_STATUS_IS_OK(status)) {
3269 goto done;
3272 /* allocate further parameters for the epm_Map call */
3274 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3275 if (res_towers == NULL) {
3276 status = NT_STATUS_NO_MEMORY;
3277 goto done;
3279 towers.twr = res_towers;
3281 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3282 if (entry_handle == NULL) {
3283 status = NT_STATUS_NO_MEMORY;
3284 goto done;
3287 /* ask the endpoint mapper for the port */
3289 status = rpccli_epm_Map(epm_pipe,
3290 tmp_ctx,
3291 CONST_DISCARD(struct GUID *,
3292 &(abstract_syntax->uuid)),
3293 map_tower,
3294 entry_handle,
3295 max_towers,
3296 &num_towers,
3297 &towers);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 goto done;
3303 if (num_towers != 1) {
3304 status = NT_STATUS_UNSUCCESSFUL;
3305 goto done;
3308 /* extract the port from the answer */
3310 status = dcerpc_binding_from_tower(tmp_ctx,
3311 &(towers.twr->tower),
3312 &res_binding);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 goto done;
3317 /* are further checks here necessary? */
3318 if (res_binding->transport != NCACN_IP_TCP) {
3319 status = NT_STATUS_UNSUCCESSFUL;
3320 goto done;
3323 *pport = (uint16_t)atoi(res_binding->endpoint);
3325 done:
3326 TALLOC_FREE(tmp_ctx);
3327 return status;
3331 * Create a rpc pipe client struct, connecting to a host via tcp.
3332 * The port is determined by asking the endpoint mapper on the given
3333 * host.
3335 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3336 const struct ndr_syntax_id *abstract_syntax,
3337 struct rpc_pipe_client **presult)
3339 NTSTATUS status;
3340 uint16_t port = 0;
3342 *presult = NULL;
3344 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3345 if (!NT_STATUS_IS_OK(status)) {
3346 goto done;
3349 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
3350 abstract_syntax, presult);
3352 done:
3353 return status;
3356 /********************************************************************
3357 Create a rpc pipe client struct, connecting to a unix domain socket
3358 ********************************************************************/
3359 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3360 const struct ndr_syntax_id *abstract_syntax,
3361 struct rpc_pipe_client **presult)
3363 struct rpc_pipe_client *result;
3364 struct sockaddr_un addr;
3365 NTSTATUS status;
3366 int fd;
3368 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3369 if (result == NULL) {
3370 return NT_STATUS_NO_MEMORY;
3373 result->abstract_syntax = *abstract_syntax;
3374 result->transfer_syntax = ndr_transfer_syntax;
3375 result->dispatch = cli_do_rpc_ndr;
3376 result->dispatch_send = cli_do_rpc_ndr_send;
3377 result->dispatch_recv = cli_do_rpc_ndr_recv;
3379 result->desthost = get_myname(result);
3380 result->srv_name_slash = talloc_asprintf_strupper_m(
3381 result, "\\\\%s", result->desthost);
3382 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3383 status = NT_STATUS_NO_MEMORY;
3384 goto fail;
3387 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3388 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3390 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3391 if (fd == -1) {
3392 status = map_nt_error_from_unix(errno);
3393 goto fail;
3396 ZERO_STRUCT(addr);
3397 addr.sun_family = AF_UNIX;
3398 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3400 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3401 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3402 strerror(errno)));
3403 close(fd);
3404 return map_nt_error_from_unix(errno);
3407 status = rpc_transport_sock_init(result, fd, &result->transport);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 close(fd);
3410 goto fail;
3413 *presult = result;
3414 return NT_STATUS_OK;
3416 fail:
3417 TALLOC_FREE(result);
3418 return status;
3421 static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p)
3423 struct cli_state *cli;
3425 cli = rpc_pipe_np_smb_conn(p);
3426 if (cli != NULL) {
3427 DLIST_REMOVE(cli->pipe_list, p);
3429 return 0;
3432 /****************************************************************************
3433 Open a named pipe over SMB to a remote server.
3435 * CAVEAT CALLER OF THIS FUNCTION:
3436 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3437 * so be sure that this function is called AFTER any structure (vs pointer)
3438 * assignment of the cli. In particular, libsmbclient does structure
3439 * assignments of cli, which invalidates the data in the returned
3440 * rpc_pipe_client if this function is called before the structure assignment
3441 * of cli.
3443 ****************************************************************************/
3445 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3446 const struct ndr_syntax_id *abstract_syntax,
3447 struct rpc_pipe_client **presult)
3449 struct rpc_pipe_client *result;
3450 NTSTATUS status;
3452 /* sanity check to protect against crashes */
3454 if ( !cli ) {
3455 return NT_STATUS_INVALID_HANDLE;
3458 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3459 if (result == NULL) {
3460 return NT_STATUS_NO_MEMORY;
3463 result->abstract_syntax = *abstract_syntax;
3464 result->transfer_syntax = ndr_transfer_syntax;
3465 result->dispatch = cli_do_rpc_ndr;
3466 result->dispatch_send = cli_do_rpc_ndr_send;
3467 result->dispatch_recv = cli_do_rpc_ndr_recv;
3468 result->desthost = talloc_strdup(result, cli->desthost);
3469 result->srv_name_slash = talloc_asprintf_strupper_m(
3470 result, "\\\\%s", result->desthost);
3472 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3473 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3475 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3476 TALLOC_FREE(result);
3477 return NT_STATUS_NO_MEMORY;
3480 status = rpc_transport_np_init(result, cli, abstract_syntax,
3481 &result->transport);
3482 if (!NT_STATUS_IS_OK(status)) {
3483 TALLOC_FREE(result);
3484 return status;
3487 DLIST_ADD(cli->pipe_list, result);
3488 talloc_set_destructor(result, rpc_pipe_client_np_destructor);
3490 *presult = result;
3491 return NT_STATUS_OK;
3494 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3495 struct rpc_cli_smbd_conn *conn,
3496 const struct ndr_syntax_id *syntax,
3497 struct rpc_pipe_client **presult)
3499 struct rpc_pipe_client *result;
3500 struct cli_pipe_auth_data *auth;
3501 NTSTATUS status;
3503 result = talloc(mem_ctx, struct rpc_pipe_client);
3504 if (result == NULL) {
3505 return NT_STATUS_NO_MEMORY;
3507 result->abstract_syntax = *syntax;
3508 result->transfer_syntax = ndr_transfer_syntax;
3509 result->dispatch = cli_do_rpc_ndr;
3510 result->dispatch_send = cli_do_rpc_ndr_send;
3511 result->dispatch_recv = cli_do_rpc_ndr_recv;
3512 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3513 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3515 result->desthost = talloc_strdup(result, global_myname());
3516 result->srv_name_slash = talloc_asprintf_strupper_m(
3517 result, "\\\\%s", global_myname());
3518 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3519 TALLOC_FREE(result);
3520 return NT_STATUS_NO_MEMORY;
3523 status = rpc_transport_smbd_init(result, conn, syntax,
3524 &result->transport);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3527 nt_errstr(status)));
3528 TALLOC_FREE(result);
3529 return status;
3532 status = rpccli_anon_bind_data(result, &auth);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3535 nt_errstr(status)));
3536 TALLOC_FREE(result);
3537 return status;
3540 status = rpc_pipe_bind(result, auth);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3543 TALLOC_FREE(result);
3544 return status;
3547 *presult = result;
3548 return NT_STATUS_OK;
3551 /****************************************************************************
3552 Open a pipe to a remote server.
3553 ****************************************************************************/
3555 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3556 const struct ndr_syntax_id *interface,
3557 struct rpc_pipe_client **presult)
3559 if (ndr_syntax_id_equal(interface, &ndr_table_drsuapi.syntax_id)) {
3561 * We should have a better way to figure out this drsuapi
3562 * speciality...
3564 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3565 presult);
3568 return rpc_pipe_open_np(cli, interface, presult);
3571 /****************************************************************************
3572 Open a named pipe to an SMB server and bind anonymously.
3573 ****************************************************************************/
3575 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3576 const struct ndr_syntax_id *interface,
3577 struct rpc_pipe_client **presult)
3579 struct rpc_pipe_client *result;
3580 struct cli_pipe_auth_data *auth;
3581 NTSTATUS status;
3583 status = cli_rpc_pipe_open(cli, interface, &result);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 return status;
3588 status = rpccli_anon_bind_data(result, &auth);
3589 if (!NT_STATUS_IS_OK(status)) {
3590 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3591 nt_errstr(status)));
3592 TALLOC_FREE(result);
3593 return status;
3597 * This is a bit of an abstraction violation due to the fact that an
3598 * anonymous bind on an authenticated SMB inherits the user/domain
3599 * from the enclosing SMB creds
3602 TALLOC_FREE(auth->user_name);
3603 TALLOC_FREE(auth->domain);
3605 auth->user_name = talloc_strdup(auth, cli->user_name);
3606 auth->domain = talloc_strdup(auth, cli->domain);
3607 auth->user_session_key = data_blob_talloc(auth,
3608 cli->user_session_key.data,
3609 cli->user_session_key.length);
3611 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3612 TALLOC_FREE(result);
3613 return NT_STATUS_NO_MEMORY;
3616 status = rpc_pipe_bind(result, auth);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 int lvl = 0;
3619 if (ndr_syntax_id_equal(interface,
3620 &ndr_table_dssetup.syntax_id)) {
3621 /* non AD domains just don't have this pipe, avoid
3622 * level 0 statement in that case - gd */
3623 lvl = 3;
3625 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3626 "%s failed with error %s\n",
3627 get_pipe_name_from_iface(interface),
3628 nt_errstr(status) ));
3629 TALLOC_FREE(result);
3630 return status;
3633 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3634 "%s and bound anonymously.\n",
3635 get_pipe_name_from_iface(interface), cli->desthost));
3637 *presult = result;
3638 return NT_STATUS_OK;
3641 /****************************************************************************
3642 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3643 ****************************************************************************/
3645 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3646 const struct ndr_syntax_id *interface,
3647 enum pipe_auth_type auth_type,
3648 enum pipe_auth_level auth_level,
3649 const char *domain,
3650 const char *username,
3651 const char *password,
3652 struct rpc_pipe_client **presult)
3654 struct rpc_pipe_client *result;
3655 struct cli_pipe_auth_data *auth;
3656 NTSTATUS status;
3658 status = cli_rpc_pipe_open(cli, interface, &result);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 return status;
3663 status = rpccli_ntlmssp_bind_data(
3664 result, auth_type, auth_level, domain, username,
3665 password, &auth);
3666 if (!NT_STATUS_IS_OK(status)) {
3667 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3668 nt_errstr(status)));
3669 goto err;
3672 status = rpc_pipe_bind(result, auth);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3675 nt_errstr(status) ));
3676 goto err;
3679 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3680 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3681 get_pipe_name_from_iface(interface), cli->desthost, domain,
3682 username ));
3684 *presult = result;
3685 return NT_STATUS_OK;
3687 err:
3689 TALLOC_FREE(result);
3690 return status;
3693 /****************************************************************************
3694 External interface.
3695 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3696 ****************************************************************************/
3698 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3699 const struct ndr_syntax_id *interface,
3700 enum pipe_auth_level auth_level,
3701 const char *domain,
3702 const char *username,
3703 const char *password,
3704 struct rpc_pipe_client **presult)
3706 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3707 interface,
3708 PIPE_AUTH_TYPE_NTLMSSP,
3709 auth_level,
3710 domain,
3711 username,
3712 password,
3713 presult);
3716 /****************************************************************************
3717 External interface.
3718 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3719 ****************************************************************************/
3721 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3722 const struct ndr_syntax_id *interface,
3723 enum pipe_auth_level auth_level,
3724 const char *domain,
3725 const char *username,
3726 const char *password,
3727 struct rpc_pipe_client **presult)
3729 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3730 interface,
3731 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3732 auth_level,
3733 domain,
3734 username,
3735 password,
3736 presult);
3739 /****************************************************************************
3740 Get a the schannel session key out of an already opened netlogon pipe.
3741 ****************************************************************************/
3742 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3743 struct cli_state *cli,
3744 const char *domain,
3745 uint32 *pneg_flags)
3747 uint32 sec_chan_type = 0;
3748 unsigned char machine_pwd[16];
3749 const char *machine_account;
3750 NTSTATUS status;
3752 /* Get the machine account credentials from secrets.tdb. */
3753 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3754 &sec_chan_type))
3756 DEBUG(0, ("get_schannel_session_key: could not fetch "
3757 "trust account password for domain '%s'\n",
3758 domain));
3759 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3762 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3763 cli->desthost, /* server name */
3764 domain, /* domain */
3765 global_myname(), /* client name */
3766 machine_account, /* machine account name */
3767 machine_pwd,
3768 sec_chan_type,
3769 pneg_flags);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 DEBUG(3, ("get_schannel_session_key_common: "
3773 "rpccli_netlogon_setup_creds failed with result %s "
3774 "to server %s, domain %s, machine account %s.\n",
3775 nt_errstr(status), cli->desthost, domain,
3776 machine_account ));
3777 return status;
3780 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3781 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3782 cli->desthost));
3783 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3786 return NT_STATUS_OK;;
3789 /****************************************************************************
3790 Open a netlogon pipe and get the schannel session key.
3791 Now exposed to external callers.
3792 ****************************************************************************/
3795 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3796 const char *domain,
3797 uint32 *pneg_flags,
3798 struct rpc_pipe_client **presult)
3800 struct rpc_pipe_client *netlogon_pipe = NULL;
3801 NTSTATUS status;
3803 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3804 &netlogon_pipe);
3805 if (!NT_STATUS_IS_OK(status)) {
3806 return status;
3809 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3810 pneg_flags);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 TALLOC_FREE(netlogon_pipe);
3813 return status;
3816 *presult = netlogon_pipe;
3817 return NT_STATUS_OK;
3820 /****************************************************************************
3821 External interface.
3822 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3823 using session_key. sign and seal.
3825 The *pdc will be stolen onto this new pipe
3826 ****************************************************************************/
3828 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3829 const struct ndr_syntax_id *interface,
3830 enum pipe_auth_level auth_level,
3831 const char *domain,
3832 struct netlogon_creds_CredentialState **pdc,
3833 struct rpc_pipe_client **presult)
3835 struct rpc_pipe_client *result;
3836 struct cli_pipe_auth_data *auth;
3837 NTSTATUS status;
3839 status = cli_rpc_pipe_open(cli, interface, &result);
3840 if (!NT_STATUS_IS_OK(status)) {
3841 return status;
3844 status = rpccli_schannel_bind_data(result, domain, auth_level,
3845 (*pdc)->session_key, &auth);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3848 nt_errstr(status)));
3849 TALLOC_FREE(result);
3850 return status;
3853 status = rpc_pipe_bind(result, auth);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3856 "cli_rpc_pipe_bind failed with error %s\n",
3857 nt_errstr(status) ));
3858 TALLOC_FREE(result);
3859 return status;
3863 * The credentials on a new netlogon pipe are the ones we are passed
3864 * in - reference them in
3866 result->dc = talloc_move(result, pdc);
3867 if (result->dc == NULL) {
3868 DEBUG(0, ("talloc reference failed\n"));
3869 TALLOC_FREE(result);
3870 return NT_STATUS_NO_MEMORY;
3873 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3874 "for domain %s and bound using schannel.\n",
3875 get_pipe_name_from_iface(interface),
3876 cli->desthost, domain ));
3878 *presult = result;
3879 return NT_STATUS_OK;
3882 /****************************************************************************
3883 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3884 Fetch the session key ourselves using a temporary netlogon pipe. This
3885 version uses an ntlmssp auth bound netlogon pipe to get the key.
3886 ****************************************************************************/
3888 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3889 const char *domain,
3890 const char *username,
3891 const char *password,
3892 uint32 *pneg_flags,
3893 struct rpc_pipe_client **presult)
3895 struct rpc_pipe_client *netlogon_pipe = NULL;
3896 NTSTATUS status;
3898 status = cli_rpc_pipe_open_spnego_ntlmssp(
3899 cli, &ndr_table_netlogon.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
3900 domain, username, password, &netlogon_pipe);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 return status;
3905 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3906 pneg_flags);
3907 if (!NT_STATUS_IS_OK(status)) {
3908 TALLOC_FREE(netlogon_pipe);
3909 return status;
3912 *presult = netlogon_pipe;
3913 return NT_STATUS_OK;
3916 /****************************************************************************
3917 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3918 Fetch the session key ourselves using a temporary netlogon pipe. This version
3919 uses an ntlmssp bind to get the session key.
3920 ****************************************************************************/
3922 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3923 const struct ndr_syntax_id *interface,
3924 enum pipe_auth_level auth_level,
3925 const char *domain,
3926 const char *username,
3927 const char *password,
3928 struct rpc_pipe_client **presult)
3930 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3931 struct rpc_pipe_client *netlogon_pipe = NULL;
3932 struct rpc_pipe_client *result = NULL;
3933 NTSTATUS status;
3935 status = get_schannel_session_key_auth_ntlmssp(
3936 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3937 if (!NT_STATUS_IS_OK(status)) {
3938 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3939 "key from server %s for domain %s.\n",
3940 cli->desthost, domain ));
3941 return status;
3944 status = cli_rpc_pipe_open_schannel_with_key(
3945 cli, interface, auth_level, domain, &netlogon_pipe->dc,
3946 &result);
3948 /* Now we've bound using the session key we can close the netlog pipe. */
3949 TALLOC_FREE(netlogon_pipe);
3951 if (NT_STATUS_IS_OK(status)) {
3952 *presult = result;
3954 return status;
3957 /****************************************************************************
3958 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3959 Fetch the session key ourselves using a temporary netlogon pipe.
3960 ****************************************************************************/
3962 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3963 const struct ndr_syntax_id *interface,
3964 enum pipe_auth_level auth_level,
3965 const char *domain,
3966 struct rpc_pipe_client **presult)
3968 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3969 struct rpc_pipe_client *netlogon_pipe = NULL;
3970 struct rpc_pipe_client *result = NULL;
3971 NTSTATUS status;
3973 status = get_schannel_session_key(cli, domain, &neg_flags,
3974 &netlogon_pipe);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3977 "key from server %s for domain %s.\n",
3978 cli->desthost, domain ));
3979 return status;
3982 status = cli_rpc_pipe_open_schannel_with_key(
3983 cli, interface, auth_level, domain, &netlogon_pipe->dc,
3984 &result);
3986 /* Now we've bound using the session key we can close the netlog pipe. */
3987 TALLOC_FREE(netlogon_pipe);
3989 if (NT_STATUS_IS_OK(status)) {
3990 *presult = result;
3993 return NT_STATUS_OK;
3996 /****************************************************************************
3997 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3998 The idea is this can be called with service_princ, username and password all
3999 NULL so long as the caller has a TGT.
4000 ****************************************************************************/
4002 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4003 const struct ndr_syntax_id *interface,
4004 enum pipe_auth_level auth_level,
4005 const char *service_princ,
4006 const char *username,
4007 const char *password,
4008 struct rpc_pipe_client **presult)
4010 #ifdef HAVE_KRB5
4011 struct rpc_pipe_client *result;
4012 struct cli_pipe_auth_data *auth;
4013 NTSTATUS status;
4015 status = cli_rpc_pipe_open(cli, interface, &result);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 return status;
4020 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4021 username, password, &auth);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4024 nt_errstr(status)));
4025 TALLOC_FREE(result);
4026 return status;
4029 status = rpc_pipe_bind(result, auth);
4030 if (!NT_STATUS_IS_OK(status)) {
4031 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4032 "with error %s\n", nt_errstr(status)));
4033 TALLOC_FREE(result);
4034 return status;
4037 *presult = result;
4038 return NT_STATUS_OK;
4039 #else
4040 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4041 return NT_STATUS_NOT_IMPLEMENTED;
4042 #endif
4045 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4046 struct rpc_pipe_client *cli,
4047 DATA_BLOB *session_key)
4049 if (!session_key || !cli) {
4050 return NT_STATUS_INVALID_PARAMETER;
4053 if (!cli->auth) {
4054 return NT_STATUS_INVALID_PARAMETER;
4057 switch (cli->auth->auth_type) {
4058 case PIPE_AUTH_TYPE_SCHANNEL:
4059 *session_key = data_blob_talloc(mem_ctx,
4060 cli->auth->a_u.schannel_auth->sess_key, 16);
4061 break;
4062 case PIPE_AUTH_TYPE_NTLMSSP:
4063 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4064 *session_key = data_blob_talloc(mem_ctx,
4065 cli->auth->a_u.ntlmssp_state->session_key.data,
4066 cli->auth->a_u.ntlmssp_state->session_key.length);
4067 break;
4068 case PIPE_AUTH_TYPE_KRB5:
4069 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4070 *session_key = data_blob_talloc(mem_ctx,
4071 cli->auth->a_u.kerberos_auth->session_key.data,
4072 cli->auth->a_u.kerberos_auth->session_key.length);
4073 break;
4074 case PIPE_AUTH_TYPE_NONE:
4075 *session_key = data_blob_talloc(mem_ctx,
4076 cli->auth->user_session_key.data,
4077 cli->auth->user_session_key.length);
4078 break;
4079 default:
4080 return NT_STATUS_NO_USER_SESSION_KEY;
4083 return NT_STATUS_OK;