Refactoring: Make get_schannel_session_key_common return NTSTATUS
[Samba.git] / source / rpc_client / cli_pipe.c
blob0ba94ea29273df848aa8e8d101f66d60c4a5e92d
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_CLI
26 /*******************************************************************
27 interface/version dce/rpc pipe identification
28 ********************************************************************/
30 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
31 #define PIPE_SAMR "\\PIPE\\samr"
32 #define PIPE_WINREG "\\PIPE\\winreg"
33 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
34 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
35 #define PIPE_NTLSA "\\PIPE\\ntlsa"
36 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
37 #define PIPE_LSASS "\\PIPE\\lsass"
38 #define PIPE_LSARPC "\\PIPE\\lsarpc"
39 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
40 #define PIPE_NETDFS "\\PIPE\\netdfs"
41 #define PIPE_ECHO "\\PIPE\\rpcecho"
42 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
43 #define PIPE_EPM "\\PIPE\\epmapper"
44 #define PIPE_SVCCTL "\\PIPE\\svcctl"
45 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
46 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
47 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
50 * IMPORTANT!! If you update this structure, make sure to
51 * update the index #defines in smb.h.
54 static const struct pipe_id_info {
55 /* the names appear not to matter: the syntaxes _do_ matter */
57 const char *client_pipe;
58 const RPC_IFACE *abstr_syntax; /* this one is the abstract syntax id */
59 } pipe_names [] =
61 { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
62 { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
63 { PIPE_SAMR, &ndr_table_samr.syntax_id },
64 { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
65 { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
66 { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
67 { PIPE_WINREG, &ndr_table_winreg.syntax_id },
68 { PIPE_SPOOLSS, &syntax_spoolss },
69 { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
70 { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
71 { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
72 { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
73 { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
74 { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
75 { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
76 { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
77 { NULL, NULL }
80 /****************************************************************************
81 Return the pipe name from the index.
82 ****************************************************************************/
84 const char *cli_get_pipe_name(int pipe_idx)
86 return &pipe_names[pipe_idx].client_pipe[5];
89 static const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx,
90 struct cli_state *cli,
91 const struct ndr_syntax_id *interface)
93 int i;
94 for (i = 0; pipe_names[i].client_pipe; i++) {
95 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
96 interface)) {
97 return cli_get_pipe_name(i);
102 * Here we should ask \\epmapper, but for now our code is only
103 * interested in the known pipes mentioned in pipe_names[]
106 return NULL;
109 /****************************************************************************
110 Return the pipe idx from the syntax.
111 ****************************************************************************/
112 int cli_get_pipe_idx(const RPC_IFACE *syntax)
114 int i;
115 for (i = 0; pipe_names[i].client_pipe; i++) {
116 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax, syntax)) {
117 return i;
121 return -1;
124 /********************************************************************
125 LEGACY function to ease transition from pipe_idx to interface
126 ********************************************************************/
127 const struct ndr_syntax_id *cli_get_iface(int pipe_idx)
129 SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
130 return pipe_names[pipe_idx].abstr_syntax;
133 /********************************************************************
134 Map internal value to wire value.
135 ********************************************************************/
137 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
139 switch (auth_type) {
141 case PIPE_AUTH_TYPE_NONE:
142 return RPC_ANONYMOUS_AUTH_TYPE;
144 case PIPE_AUTH_TYPE_NTLMSSP:
145 return RPC_NTLMSSP_AUTH_TYPE;
147 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
148 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
149 return RPC_SPNEGO_AUTH_TYPE;
151 case PIPE_AUTH_TYPE_SCHANNEL:
152 return RPC_SCHANNEL_AUTH_TYPE;
154 case PIPE_AUTH_TYPE_KRB5:
155 return RPC_KRB5_AUTH_TYPE;
157 default:
158 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
159 "auth type %u\n",
160 (unsigned int)auth_type ));
161 break;
163 return -1;
166 /********************************************************************
167 Pipe description for a DEBUG
168 ********************************************************************/
169 static char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli)
171 char *result;
173 switch (cli->transport_type) {
174 case NCACN_NP:
175 result = talloc_asprintf(mem_ctx, "host %s, pipe %s, "
176 "fnum 0x%x",
177 cli->desthost,
178 cli->trans.np.pipe_name,
179 (unsigned int)(cli->trans.np.fnum));
180 break;
181 case NCACN_IP_TCP:
182 case NCACN_UNIX_STREAM:
183 result = talloc_asprintf(mem_ctx, "host %s, fd %d",
184 cli->desthost, cli->trans.sock.fd);
185 break;
186 default:
187 result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
188 break;
190 SMB_ASSERT(result != NULL);
191 return result;
194 /********************************************************************
195 Rpc pipe call id.
196 ********************************************************************/
198 static uint32 get_rpc_call_id(void)
200 static uint32 call_id = 0;
201 return ++call_id;
204 /*******************************************************************
205 Read from a RPC named pipe
206 ********************************************************************/
207 static NTSTATUS rpc_read_np(struct cli_state *cli, const char *pipe_name,
208 int fnum, char *buf, off_t offset, size_t size,
209 ssize_t *pnum_read)
211 ssize_t num_read;
213 num_read = cli_read(cli, fnum, buf, offset, size);
215 DEBUG(5,("rpc_read_np: num_read = %d, read offset: %u, to read: %u\n",
216 (int)num_read, (unsigned int)offset, (unsigned int)size));
219 * A dos error of ERRDOS/ERRmoredata is not an error.
221 if (cli_is_dos_error(cli)) {
222 uint32 ecode;
223 uint8 eclass;
224 cli_dos_error(cli, &eclass, &ecode);
225 if (eclass != ERRDOS && ecode != ERRmoredata) {
226 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read "
227 "on fnum 0x%x\n", eclass, (unsigned int)ecode,
228 cli_errstr(cli), fnum));
229 return dos_to_ntstatus(eclass, ecode);
234 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
236 if (cli_is_nt_error(cli)) {
237 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
238 NT_STATUS_BUFFER_TOO_SMALL)) {
239 DEBUG(0,("rpc_read: Error (%s) in cli_read on fnum "
240 "0x%x\n", nt_errstr(cli_nt_error(cli)), fnum));
241 return cli_nt_error(cli);
245 if (num_read == -1) {
246 DEBUG(0,("rpc_read: Error - cli_read on fnum 0x%x returned "
247 "-1\n", fnum));
248 return cli_get_nt_error(cli);
251 *pnum_read = num_read;
252 return NT_STATUS_OK;
256 /*******************************************************************
257 Use SMBreadX to get rest of one fragment's worth of rpc data.
258 Will expand the current_pdu struct to the correct size.
259 ********************************************************************/
261 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
262 prs_struct *current_pdu,
263 uint32 data_to_read,
264 uint32 *current_pdu_offset)
266 size_t size = (size_t)cli->max_recv_frag;
267 uint32 stream_offset = 0;
268 ssize_t num_read = 0;
269 char *pdata;
270 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
272 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
273 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
276 * Grow the buffer if needed to accommodate the data to be read.
279 if (extra_data_size > 0) {
280 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
281 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
282 return NT_STATUS_NO_MEMORY;
284 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
287 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
289 do {
290 NTSTATUS status;
292 /* read data using SMBreadX */
293 if (size > (size_t)data_to_read) {
294 size = (size_t)data_to_read;
297 switch (cli->transport_type) {
298 case NCACN_NP:
299 status = rpc_read_np(cli->trans.np.cli,
300 cli->trans.np.pipe_name,
301 cli->trans.np.fnum, pdata,
302 (off_t)stream_offset, size,
303 &num_read);
304 break;
305 case NCACN_IP_TCP:
306 case NCACN_UNIX_STREAM:
307 status = NT_STATUS_OK;
308 num_read = sys_read(cli->trans.sock.fd, pdata, size);
309 if (num_read == -1) {
310 status = map_nt_error_from_unix(errno);
312 if (num_read == 0) {
313 status = NT_STATUS_END_OF_FILE;
315 break;
316 default:
317 DEBUG(0, ("unknown transport type %d\n",
318 cli->transport_type));
319 return NT_STATUS_INTERNAL_ERROR;
322 data_to_read -= num_read;
323 stream_offset += num_read;
324 pdata += num_read;
326 } while (num_read > 0 && data_to_read > 0);
327 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
330 * Update the current offset into current_pdu by the amount read.
332 *current_pdu_offset += stream_offset;
333 return NT_STATUS_OK;
336 /****************************************************************************
337 Try and get a PDU's worth of data from current_pdu. If not, then read more
338 from the wire.
339 ****************************************************************************/
341 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
343 NTSTATUS ret = NT_STATUS_OK;
344 uint32 current_pdu_len = prs_data_size(current_pdu);
346 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
347 if (current_pdu_len < RPC_HEADER_LEN) {
348 /* rpc_read expands the current_pdu struct as neccessary. */
349 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
350 if (!NT_STATUS_IS_OK(ret)) {
351 return ret;
355 /* This next call sets the endian bit correctly in current_pdu. */
356 /* We will propagate this to rbuf later. */
357 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
358 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
359 return NT_STATUS_BUFFER_TOO_SMALL;
362 /* Ensure we have frag_len bytes of data. */
363 if (current_pdu_len < prhdr->frag_len) {
364 /* rpc_read expands the current_pdu struct as neccessary. */
365 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
366 if (!NT_STATUS_IS_OK(ret)) {
367 return ret;
371 if (current_pdu_len < prhdr->frag_len) {
372 return NT_STATUS_BUFFER_TOO_SMALL;
375 return NT_STATUS_OK;
378 /****************************************************************************
379 NTLMSSP specific sign/seal.
380 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
381 In fact I should probably abstract these into identical pieces of code... JRA.
382 ****************************************************************************/
384 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
385 prs_struct *current_pdu,
386 uint8 *p_ss_padding_len)
388 RPC_HDR_AUTH auth_info;
389 uint32 save_offset = prs_offset(current_pdu);
390 uint32 auth_len = prhdr->auth_len;
391 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
392 unsigned char *data = NULL;
393 size_t data_len;
394 unsigned char *full_packet_data = NULL;
395 size_t full_packet_data_len;
396 DATA_BLOB auth_blob;
397 NTSTATUS status;
399 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
400 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
401 return NT_STATUS_OK;
404 if (!ntlmssp_state) {
405 return NT_STATUS_INVALID_PARAMETER;
408 /* Ensure there's enough data for an authenticated response. */
409 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
410 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
411 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
412 (unsigned int)auth_len ));
413 return NT_STATUS_BUFFER_TOO_SMALL;
417 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
418 * after the RPC header.
419 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
420 * functions as NTLMv2 checks the rpc headers also.
423 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
424 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
426 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
427 full_packet_data_len = prhdr->frag_len - auth_len;
429 /* Pull the auth header and the following data into a blob. */
430 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
431 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
432 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
433 return NT_STATUS_BUFFER_TOO_SMALL;
436 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
437 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
438 return NT_STATUS_BUFFER_TOO_SMALL;
441 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
442 auth_blob.length = auth_len;
444 switch (cli->auth->auth_level) {
445 case PIPE_AUTH_LEVEL_PRIVACY:
446 /* Data is encrypted. */
447 status = ntlmssp_unseal_packet(ntlmssp_state,
448 data, data_len,
449 full_packet_data,
450 full_packet_data_len,
451 &auth_blob);
452 if (!NT_STATUS_IS_OK(status)) {
453 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
454 "packet from %s. Error was %s.\n",
455 rpccli_pipe_txt(debug_ctx(), cli),
456 nt_errstr(status) ));
457 return status;
459 break;
460 case PIPE_AUTH_LEVEL_INTEGRITY:
461 /* Data is signed. */
462 status = ntlmssp_check_packet(ntlmssp_state,
463 data, data_len,
464 full_packet_data,
465 full_packet_data_len,
466 &auth_blob);
467 if (!NT_STATUS_IS_OK(status)) {
468 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
469 "packet from %s. Error was %s.\n",
470 rpccli_pipe_txt(debug_ctx(), cli),
471 nt_errstr(status) ));
472 return status;
474 break;
475 default:
476 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
477 "auth level %d\n", cli->auth->auth_level));
478 return NT_STATUS_INVALID_INFO_CLASS;
482 * Return the current pointer to the data offset.
485 if(!prs_set_offset(current_pdu, save_offset)) {
486 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
487 (unsigned int)save_offset ));
488 return NT_STATUS_BUFFER_TOO_SMALL;
492 * Remember the padding length. We must remove it from the real data
493 * stream once the sign/seal is done.
496 *p_ss_padding_len = auth_info.auth_pad_len;
498 return NT_STATUS_OK;
501 /****************************************************************************
502 schannel specific sign/seal.
503 ****************************************************************************/
505 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
506 prs_struct *current_pdu,
507 uint8 *p_ss_padding_len)
509 RPC_HDR_AUTH auth_info;
510 RPC_AUTH_SCHANNEL_CHK schannel_chk;
511 uint32 auth_len = prhdr->auth_len;
512 uint32 save_offset = prs_offset(current_pdu);
513 struct schannel_auth_struct *schannel_auth =
514 cli->auth->a_u.schannel_auth;
515 uint32 data_len;
517 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
518 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
519 return NT_STATUS_OK;
522 if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
523 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
524 return NT_STATUS_INVALID_PARAMETER;
527 if (!schannel_auth) {
528 return NT_STATUS_INVALID_PARAMETER;
531 /* Ensure there's enough data for an authenticated response. */
532 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
533 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
534 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
535 (unsigned int)auth_len ));
536 return NT_STATUS_INVALID_PARAMETER;
539 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
541 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
542 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
543 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
544 return NT_STATUS_BUFFER_TOO_SMALL;
547 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
548 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
549 return NT_STATUS_BUFFER_TOO_SMALL;
552 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
553 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
554 auth_info.auth_type));
555 return NT_STATUS_BUFFER_TOO_SMALL;
558 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
559 &schannel_chk, current_pdu, 0)) {
560 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
561 return NT_STATUS_BUFFER_TOO_SMALL;
564 if (!schannel_decode(schannel_auth,
565 cli->auth->auth_level,
566 SENDER_IS_ACCEPTOR,
567 &schannel_chk,
568 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
569 data_len)) {
570 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
571 "Connection to %s.\n",
572 rpccli_pipe_txt(debug_ctx(), cli)));
573 return NT_STATUS_INVALID_PARAMETER;
576 /* The sequence number gets incremented on both send and receive. */
577 schannel_auth->seq_num++;
580 * Return the current pointer to the data offset.
583 if(!prs_set_offset(current_pdu, save_offset)) {
584 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
585 (unsigned int)save_offset ));
586 return NT_STATUS_BUFFER_TOO_SMALL;
590 * Remember the padding length. We must remove it from the real data
591 * stream once the sign/seal is done.
594 *p_ss_padding_len = auth_info.auth_pad_len;
596 return NT_STATUS_OK;
599 /****************************************************************************
600 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
601 ****************************************************************************/
603 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
604 prs_struct *current_pdu,
605 uint8 *p_ss_padding_len)
607 NTSTATUS ret = NT_STATUS_OK;
609 /* Paranioa checks for auth_len. */
610 if (prhdr->auth_len) {
611 if (prhdr->auth_len > prhdr->frag_len) {
612 return NT_STATUS_INVALID_PARAMETER;
615 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
616 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
617 /* Integer wrap attempt. */
618 return NT_STATUS_INVALID_PARAMETER;
623 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
626 switch(cli->auth->auth_type) {
627 case PIPE_AUTH_TYPE_NONE:
628 if (prhdr->auth_len) {
629 DEBUG(3, ("cli_pipe_validate_rpc_response: "
630 "Connection to %s - got non-zero "
631 "auth len %u.\n",
632 rpccli_pipe_txt(debug_ctx(), cli),
633 (unsigned int)prhdr->auth_len ));
634 return NT_STATUS_INVALID_PARAMETER;
636 break;
638 case PIPE_AUTH_TYPE_NTLMSSP:
639 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
640 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
641 if (!NT_STATUS_IS_OK(ret)) {
642 return ret;
644 break;
646 case PIPE_AUTH_TYPE_SCHANNEL:
647 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
648 if (!NT_STATUS_IS_OK(ret)) {
649 return ret;
651 break;
653 case PIPE_AUTH_TYPE_KRB5:
654 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
655 default:
656 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
657 "to %s - unknown internal auth type %u.\n",
658 rpccli_pipe_txt(debug_ctx(), cli),
659 cli->auth->auth_type ));
660 return NT_STATUS_INVALID_INFO_CLASS;
663 return NT_STATUS_OK;
666 /****************************************************************************
667 Do basic authentication checks on an incoming pdu.
668 ****************************************************************************/
670 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
671 prs_struct *current_pdu,
672 uint8 expected_pkt_type,
673 char **ppdata,
674 uint32 *pdata_len,
675 prs_struct *return_data)
678 NTSTATUS ret = NT_STATUS_OK;
679 uint32 current_pdu_len = prs_data_size(current_pdu);
681 if (current_pdu_len != prhdr->frag_len) {
682 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
683 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
684 return NT_STATUS_INVALID_PARAMETER;
688 * Point the return values at the real data including the RPC
689 * header. Just in case the caller wants it.
691 *ppdata = prs_data_p(current_pdu);
692 *pdata_len = current_pdu_len;
694 /* Ensure we have the correct type. */
695 switch (prhdr->pkt_type) {
696 case RPC_ALTCONTRESP:
697 case RPC_BINDACK:
699 /* Alter context and bind ack share the same packet definitions. */
700 break;
703 case RPC_RESPONSE:
705 RPC_HDR_RESP rhdr_resp;
706 uint8 ss_padding_len = 0;
708 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
709 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
710 return NT_STATUS_BUFFER_TOO_SMALL;
713 /* Here's where we deal with incoming sign/seal. */
714 ret = cli_pipe_validate_rpc_response(cli, prhdr,
715 current_pdu, &ss_padding_len);
716 if (!NT_STATUS_IS_OK(ret)) {
717 return ret;
720 /* Point the return values at the NDR data. Remember to remove any ss padding. */
721 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
723 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
724 return NT_STATUS_BUFFER_TOO_SMALL;
727 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
729 /* Remember to remove the auth footer. */
730 if (prhdr->auth_len) {
731 /* We've already done integer wrap tests on auth_len in
732 cli_pipe_validate_rpc_response(). */
733 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
734 return NT_STATUS_BUFFER_TOO_SMALL;
736 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
739 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
740 current_pdu_len, *pdata_len, ss_padding_len ));
743 * If this is the first reply, and the allocation hint is reasonably, try and
744 * set up the return_data parse_struct to the correct size.
747 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
748 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
749 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
750 "too large to allocate\n",
751 (unsigned int)rhdr_resp.alloc_hint ));
752 return NT_STATUS_NO_MEMORY;
756 break;
759 case RPC_BINDNACK:
760 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
761 "received from %s!\n",
762 rpccli_pipe_txt(debug_ctx(), cli)));
763 /* Use this for now... */
764 return NT_STATUS_NETWORK_ACCESS_DENIED;
766 case RPC_FAULT:
768 RPC_HDR_RESP rhdr_resp;
769 RPC_HDR_FAULT fault_resp;
771 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
772 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
773 return NT_STATUS_BUFFER_TOO_SMALL;
776 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
777 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
778 return NT_STATUS_BUFFER_TOO_SMALL;
781 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
782 "code %s received from %s!\n",
783 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
784 rpccli_pipe_txt(debug_ctx(), cli)));
785 if (NT_STATUS_IS_OK(fault_resp.status)) {
786 return NT_STATUS_UNSUCCESSFUL;
787 } else {
788 return fault_resp.status;
792 default:
793 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
794 "from %s!\n",
795 (unsigned int)prhdr->pkt_type,
796 rpccli_pipe_txt(debug_ctx(), cli)));
797 return NT_STATUS_INVALID_INFO_CLASS;
800 if (prhdr->pkt_type != expected_pkt_type) {
801 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
802 "got an unexpected RPC packet type - %u, not %u\n",
803 rpccli_pipe_txt(debug_ctx(), cli),
804 prhdr->pkt_type,
805 expected_pkt_type));
806 return NT_STATUS_INVALID_INFO_CLASS;
809 /* Do this just before return - we don't want to modify any rpc header
810 data before now as we may have needed to do cryptographic actions on
811 it before. */
813 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
814 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
815 "setting fragment first/last ON.\n"));
816 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
819 return NT_STATUS_OK;
822 /****************************************************************************
823 Ensure we eat the just processed pdu from the current_pdu prs_struct.
824 Normally the frag_len and buffer size will match, but on the first trans
825 reply there is a theoretical chance that buffer size > frag_len, so we must
826 deal with that.
827 ****************************************************************************/
829 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
831 uint32 current_pdu_len = prs_data_size(current_pdu);
833 if (current_pdu_len < prhdr->frag_len) {
834 return NT_STATUS_BUFFER_TOO_SMALL;
837 /* Common case. */
838 if (current_pdu_len == (uint32)prhdr->frag_len) {
839 prs_mem_free(current_pdu);
840 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
841 /* Make current_pdu dynamic with no memory. */
842 prs_give_memory(current_pdu, 0, 0, True);
843 return NT_STATUS_OK;
847 * Oh no ! More data in buffer than we processed in current pdu.
848 * Cheat. Move the data down and shrink the buffer.
851 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
852 current_pdu_len - prhdr->frag_len);
854 /* Remember to set the read offset back to zero. */
855 prs_set_offset(current_pdu, 0);
857 /* Shrink the buffer. */
858 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
859 return NT_STATUS_BUFFER_TOO_SMALL;
862 return NT_STATUS_OK;
865 /****************************************************************************
866 Send data on an rpc pipe via trans. The prs_struct data must be the last
867 pdu fragment of an NDR data stream.
869 Receive response data from an rpc pipe, which may be large...
871 Read the first fragment: unfortunately have to use SMBtrans for the first
872 bit, then SMBreadX for subsequent bits.
874 If first fragment received also wasn't the last fragment, continue
875 getting fragments until we _do_ receive the last fragment.
877 Request/Response PDU's look like the following...
879 |<------------------PDU len----------------------------------------------->|
880 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
882 +------------+-----------------+-------------+---------------+-------------+
883 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
884 +------------+-----------------+-------------+---------------+-------------+
886 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
887 signing & sealing being negotiated.
889 ****************************************************************************/
891 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
892 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
893 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
894 uint8 expected_pkt_type)
896 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
897 char *rparam = NULL;
898 uint32 rparam_len = 0;
899 char *pdata = prs_data_p(data);
900 uint32 data_len = prs_offset(data);
901 char *prdata = NULL;
902 uint32 rdata_len = 0;
903 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
904 uint32 current_rbuf_offset = 0;
905 prs_struct current_pdu;
907 #ifdef DEVELOPER
908 /* Ensure we're not sending too much. */
909 SMB_ASSERT(data_len <= max_data);
910 #endif
912 /* Set up the current pdu parse struct. */
913 prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
915 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
917 switch (cli->transport_type) {
918 case NCACN_NP: {
919 uint16 setup[2];
920 /* Create setup parameters - must be in native byte order. */
921 setup[0] = TRANSACT_DCERPCCMD;
922 setup[1] = cli->trans.np.fnum; /* Pipe file handle. */
925 * Send the last (or only) fragment of an RPC request. For
926 * small amounts of data (about 1024 bytes or so) the RPC
927 * request and response appears in a SMBtrans request and
928 * response.
931 if (!cli_api_pipe(cli->trans.np.cli, "\\PIPE\\",
932 setup, 2, 0, /* Setup, length, max */
933 NULL, 0, 0, /* Params, length, max */
934 pdata, data_len, max_data, /* data, length,
935 * max */
936 &rparam, &rparam_len, /* return params,
937 * len */
938 &prdata, &rdata_len)) /* return data, len */
940 DEBUG(0, ("rpc_api_pipe: %s returned critical error. "
941 "Error was %s\n",
942 rpccli_pipe_txt(debug_ctx(), cli),
943 cli_errstr(cli->trans.np.cli)));
944 ret = cli_get_nt_error(cli->trans.np.cli);
945 SAFE_FREE(rparam);
946 SAFE_FREE(prdata);
947 goto err;
949 break;
951 case NCACN_IP_TCP:
952 case NCACN_UNIX_STREAM:
954 ssize_t nwritten, nread;
955 nwritten = write_data(cli->trans.sock.fd, pdata, data_len);
956 if (nwritten == -1) {
957 ret = map_nt_error_from_unix(errno);
958 DEBUG(0, ("rpc_api_pipe: write_data returned %s\n",
959 strerror(errno)));
960 goto err;
962 rparam = NULL;
963 prdata = SMB_MALLOC_ARRAY(char, 1);
964 if (prdata == NULL) {
965 return NT_STATUS_NO_MEMORY;
967 nread = sys_read(cli->trans.sock.fd, prdata, 1);
968 if (nread == 0) {
969 SAFE_FREE(prdata);
971 if (nread == -1) {
972 ret = NT_STATUS_END_OF_FILE;
973 goto err;
975 rdata_len = nread;
976 break;
978 default:
979 DEBUG(0, ("unknown transport type %d\n",
980 cli->transport_type));
981 return NT_STATUS_INTERNAL_ERROR;
984 /* Throw away returned params - we know we won't use them. */
986 SAFE_FREE(rparam);
988 if (prdata == NULL) {
989 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
990 rpccli_pipe_txt(debug_ctx(), cli)));
991 /* Yes - some calls can truely return no data... */
992 prs_mem_free(&current_pdu);
993 return NT_STATUS_OK;
997 * Give this memory as dynamic to the current pdu.
1000 prs_give_memory(&current_pdu, prdata, rdata_len, True);
1002 /* Ensure we can mess with the return prs_struct. */
1003 SMB_ASSERT(UNMARSHALLING(rbuf));
1004 SMB_ASSERT(prs_data_size(rbuf) == 0);
1006 /* Make rbuf dynamic with no memory. */
1007 prs_give_memory(rbuf, 0, 0, True);
1009 while(1) {
1010 RPC_HDR rhdr;
1011 char *ret_data;
1012 uint32 ret_data_len;
1014 /* Ensure we have enough data for a pdu. */
1015 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
1016 if (!NT_STATUS_IS_OK(ret)) {
1017 goto err;
1020 /* We pass in rbuf here so if the alloc hint is set correctly
1021 we can set the output size and avoid reallocs. */
1023 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
1024 &ret_data, &ret_data_len, rbuf);
1026 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
1027 prs_data_size(&current_pdu), current_rbuf_offset ));
1029 if (!NT_STATUS_IS_OK(ret)) {
1030 goto err;
1033 if ((rhdr.flags & RPC_FLG_FIRST)) {
1034 if (rhdr.pack_type[0] == 0) {
1035 /* Set the data type correctly for big-endian data on the first packet. */
1036 DEBUG(10,("rpc_api_pipe: On %s "
1037 "PDU data format is big-endian.\n",
1038 rpccli_pipe_txt(debug_ctx(), cli)));
1040 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
1041 } else {
1042 /* Check endianness on subsequent packets. */
1043 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
1044 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
1045 rbuf->bigendian_data ? "big" : "little",
1046 current_pdu.bigendian_data ? "big" : "little" ));
1047 ret = NT_STATUS_INVALID_PARAMETER;
1048 goto err;
1053 /* Now copy the data portion out of the pdu into rbuf. */
1054 if (!prs_force_grow(rbuf, ret_data_len)) {
1055 ret = NT_STATUS_NO_MEMORY;
1056 goto err;
1058 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
1059 current_rbuf_offset += ret_data_len;
1061 /* See if we've finished with all the data in current_pdu yet ? */
1062 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
1063 if (!NT_STATUS_IS_OK(ret)) {
1064 goto err;
1067 if (rhdr.flags & RPC_FLG_LAST) {
1068 break; /* We're done. */
1072 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1073 rpccli_pipe_txt(debug_ctx(), cli),
1074 (unsigned int)prs_data_size(rbuf) ));
1076 prs_mem_free(&current_pdu);
1077 return NT_STATUS_OK;
1079 err:
1081 prs_mem_free(&current_pdu);
1082 prs_mem_free(rbuf);
1083 return ret;
1086 /*******************************************************************
1087 Creates krb5 auth bind.
1088 ********************************************************************/
1090 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1091 enum pipe_auth_level auth_level,
1092 RPC_HDR_AUTH *pauth_out,
1093 prs_struct *auth_data)
1095 #ifdef HAVE_KRB5
1096 int ret;
1097 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1098 DATA_BLOB tkt = data_blob_null;
1099 DATA_BLOB tkt_wrapped = data_blob_null;
1101 /* We may change the pad length before marshalling. */
1102 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
1104 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1105 a->service_principal ));
1107 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1109 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1110 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
1112 if (ret) {
1113 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1114 "failed with %s\n",
1115 a->service_principal,
1116 error_message(ret) ));
1118 data_blob_free(&tkt);
1119 prs_mem_free(auth_data);
1120 return NT_STATUS_INVALID_PARAMETER;
1123 /* wrap that up in a nice GSS-API wrapping */
1124 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1126 data_blob_free(&tkt);
1128 /* Auth len in the rpc header doesn't include auth_header. */
1129 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1130 data_blob_free(&tkt_wrapped);
1131 prs_mem_free(auth_data);
1132 return NT_STATUS_NO_MEMORY;
1135 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1136 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1138 data_blob_free(&tkt_wrapped);
1139 return NT_STATUS_OK;
1140 #else
1141 return NT_STATUS_INVALID_PARAMETER;
1142 #endif
1145 /*******************************************************************
1146 Creates SPNEGO NTLMSSP auth bind.
1147 ********************************************************************/
1149 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1150 enum pipe_auth_level auth_level,
1151 RPC_HDR_AUTH *pauth_out,
1152 prs_struct *auth_data)
1154 NTSTATUS nt_status;
1155 DATA_BLOB null_blob = data_blob_null;
1156 DATA_BLOB request = data_blob_null;
1157 DATA_BLOB spnego_msg = data_blob_null;
1159 /* We may change the pad length before marshalling. */
1160 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1162 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1163 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1164 null_blob,
1165 &request);
1167 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1168 data_blob_free(&request);
1169 prs_mem_free(auth_data);
1170 return nt_status;
1173 /* Wrap this in SPNEGO. */
1174 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1176 data_blob_free(&request);
1178 /* Auth len in the rpc header doesn't include auth_header. */
1179 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1180 data_blob_free(&spnego_msg);
1181 prs_mem_free(auth_data);
1182 return NT_STATUS_NO_MEMORY;
1185 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1186 dump_data(5, spnego_msg.data, spnego_msg.length);
1188 data_blob_free(&spnego_msg);
1189 return NT_STATUS_OK;
1192 /*******************************************************************
1193 Creates NTLMSSP auth bind.
1194 ********************************************************************/
1196 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1197 enum pipe_auth_level auth_level,
1198 RPC_HDR_AUTH *pauth_out,
1199 prs_struct *auth_data)
1201 NTSTATUS nt_status;
1202 DATA_BLOB null_blob = data_blob_null;
1203 DATA_BLOB request = data_blob_null;
1205 /* We may change the pad length before marshalling. */
1206 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1208 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1209 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1210 null_blob,
1211 &request);
1213 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1214 data_blob_free(&request);
1215 prs_mem_free(auth_data);
1216 return nt_status;
1219 /* Auth len in the rpc header doesn't include auth_header. */
1220 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1221 data_blob_free(&request);
1222 prs_mem_free(auth_data);
1223 return NT_STATUS_NO_MEMORY;
1226 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1227 dump_data(5, request.data, request.length);
1229 data_blob_free(&request);
1230 return NT_STATUS_OK;
1233 /*******************************************************************
1234 Creates schannel auth bind.
1235 ********************************************************************/
1237 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1238 enum pipe_auth_level auth_level,
1239 RPC_HDR_AUTH *pauth_out,
1240 prs_struct *auth_data)
1242 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1244 /* We may change the pad length before marshalling. */
1245 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1247 /* Use lp_workgroup() if domain not specified */
1249 if (!cli->auth->domain || !cli->auth->domain[0]) {
1250 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1251 if (cli->auth->domain == NULL) {
1252 return NT_STATUS_NO_MEMORY;
1256 init_rpc_auth_schannel_neg(&schannel_neg, cli->auth->domain,
1257 global_myname());
1260 * Now marshall the data into the auth parse_struct.
1263 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1264 &schannel_neg, auth_data, 0)) {
1265 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1266 prs_mem_free(auth_data);
1267 return NT_STATUS_NO_MEMORY;
1270 return NT_STATUS_OK;
1273 /*******************************************************************
1274 Creates the internals of a DCE/RPC bind request or alter context PDU.
1275 ********************************************************************/
1277 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1278 prs_struct *rpc_out,
1279 uint32 rpc_call_id,
1280 const RPC_IFACE *abstract,
1281 const RPC_IFACE *transfer,
1282 RPC_HDR_AUTH *phdr_auth,
1283 prs_struct *pauth_info)
1285 RPC_HDR hdr;
1286 RPC_HDR_RB hdr_rb;
1287 RPC_CONTEXT rpc_ctx;
1288 uint16 auth_len = prs_offset(pauth_info);
1289 uint8 ss_padding_len = 0;
1290 uint16 frag_len = 0;
1292 /* create the RPC context. */
1293 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1295 /* create the bind request RPC_HDR_RB */
1296 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1298 /* Start building the frag length. */
1299 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1301 /* Do we need to pad ? */
1302 if (auth_len) {
1303 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1304 if (data_len % 8) {
1305 ss_padding_len = 8 - (data_len % 8);
1306 phdr_auth->auth_pad_len = ss_padding_len;
1308 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1311 /* Create the request RPC_HDR */
1312 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1314 /* Marshall the RPC header */
1315 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1316 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1317 return NT_STATUS_NO_MEMORY;
1320 /* Marshall the bind request data */
1321 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1322 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1323 return NT_STATUS_NO_MEMORY;
1327 * Grow the outgoing buffer to store any auth info.
1330 if(auth_len != 0) {
1331 if (ss_padding_len) {
1332 char pad[8];
1333 memset(pad, '\0', 8);
1334 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1335 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1336 return NT_STATUS_NO_MEMORY;
1340 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1341 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1342 return NT_STATUS_NO_MEMORY;
1346 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1347 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1348 return NT_STATUS_NO_MEMORY;
1352 return NT_STATUS_OK;
1355 /*******************************************************************
1356 Creates a DCE/RPC bind request.
1357 ********************************************************************/
1359 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1360 prs_struct *rpc_out,
1361 uint32 rpc_call_id,
1362 const RPC_IFACE *abstract,
1363 const RPC_IFACE *transfer,
1364 enum pipe_auth_type auth_type,
1365 enum pipe_auth_level auth_level)
1367 RPC_HDR_AUTH hdr_auth;
1368 prs_struct auth_info;
1369 NTSTATUS ret = NT_STATUS_OK;
1371 ZERO_STRUCT(hdr_auth);
1372 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1373 return NT_STATUS_NO_MEMORY;
1375 switch (auth_type) {
1376 case PIPE_AUTH_TYPE_SCHANNEL:
1377 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1378 if (!NT_STATUS_IS_OK(ret)) {
1379 prs_mem_free(&auth_info);
1380 return ret;
1382 break;
1384 case PIPE_AUTH_TYPE_NTLMSSP:
1385 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1386 if (!NT_STATUS_IS_OK(ret)) {
1387 prs_mem_free(&auth_info);
1388 return ret;
1390 break;
1392 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1393 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1394 if (!NT_STATUS_IS_OK(ret)) {
1395 prs_mem_free(&auth_info);
1396 return ret;
1398 break;
1400 case PIPE_AUTH_TYPE_KRB5:
1401 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1402 if (!NT_STATUS_IS_OK(ret)) {
1403 prs_mem_free(&auth_info);
1404 return ret;
1406 break;
1408 case PIPE_AUTH_TYPE_NONE:
1409 break;
1411 default:
1412 /* "Can't" happen. */
1413 return NT_STATUS_INVALID_INFO_CLASS;
1416 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1417 rpc_out,
1418 rpc_call_id,
1419 abstract,
1420 transfer,
1421 &hdr_auth,
1422 &auth_info);
1424 prs_mem_free(&auth_info);
1425 return ret;
1428 /*******************************************************************
1429 Create and add the NTLMSSP sign/seal auth header and data.
1430 ********************************************************************/
1432 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1433 RPC_HDR *phdr,
1434 uint32 ss_padding_len,
1435 prs_struct *outgoing_pdu)
1437 RPC_HDR_AUTH auth_info;
1438 NTSTATUS status;
1439 DATA_BLOB auth_blob = data_blob_null;
1440 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1442 if (!cli->auth->a_u.ntlmssp_state) {
1443 return NT_STATUS_INVALID_PARAMETER;
1446 /* Init and marshall the auth header. */
1447 init_rpc_hdr_auth(&auth_info,
1448 map_pipe_auth_type_to_rpc_auth_type(
1449 cli->auth->auth_type),
1450 cli->auth->auth_level,
1451 ss_padding_len,
1452 1 /* context id. */);
1454 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1455 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1456 data_blob_free(&auth_blob);
1457 return NT_STATUS_NO_MEMORY;
1460 switch (cli->auth->auth_level) {
1461 case PIPE_AUTH_LEVEL_PRIVACY:
1462 /* Data portion is encrypted. */
1463 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1464 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1465 data_and_pad_len,
1466 (unsigned char *)prs_data_p(outgoing_pdu),
1467 (size_t)prs_offset(outgoing_pdu),
1468 &auth_blob);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 data_blob_free(&auth_blob);
1471 return status;
1473 break;
1475 case PIPE_AUTH_LEVEL_INTEGRITY:
1476 /* Data is signed. */
1477 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1478 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1479 data_and_pad_len,
1480 (unsigned char *)prs_data_p(outgoing_pdu),
1481 (size_t)prs_offset(outgoing_pdu),
1482 &auth_blob);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 data_blob_free(&auth_blob);
1485 return status;
1487 break;
1489 default:
1490 /* Can't happen. */
1491 smb_panic("bad auth level");
1492 /* Notreached. */
1493 return NT_STATUS_INVALID_PARAMETER;
1496 /* Finally marshall the blob. */
1498 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1499 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1500 (unsigned int)NTLMSSP_SIG_SIZE));
1501 data_blob_free(&auth_blob);
1502 return NT_STATUS_NO_MEMORY;
1505 data_blob_free(&auth_blob);
1506 return NT_STATUS_OK;
1509 /*******************************************************************
1510 Create and add the schannel sign/seal auth header and data.
1511 ********************************************************************/
1513 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1514 RPC_HDR *phdr,
1515 uint32 ss_padding_len,
1516 prs_struct *outgoing_pdu)
1518 RPC_HDR_AUTH auth_info;
1519 RPC_AUTH_SCHANNEL_CHK verf;
1520 struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
1521 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1522 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1524 if (!sas) {
1525 return NT_STATUS_INVALID_PARAMETER;
1528 /* Init and marshall the auth header. */
1529 init_rpc_hdr_auth(&auth_info,
1530 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1531 cli->auth->auth_level,
1532 ss_padding_len,
1533 1 /* context id. */);
1535 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1536 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1537 return NT_STATUS_NO_MEMORY;
1540 switch (cli->auth->auth_level) {
1541 case PIPE_AUTH_LEVEL_PRIVACY:
1542 case PIPE_AUTH_LEVEL_INTEGRITY:
1543 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1544 sas->seq_num));
1546 schannel_encode(sas,
1547 cli->auth->auth_level,
1548 SENDER_IS_INITIATOR,
1549 &verf,
1550 data_p,
1551 data_and_pad_len);
1553 sas->seq_num++;
1554 break;
1556 default:
1557 /* Can't happen. */
1558 smb_panic("bad auth level");
1559 /* Notreached. */
1560 return NT_STATUS_INVALID_PARAMETER;
1563 /* Finally marshall the blob. */
1564 smb_io_rpc_auth_schannel_chk("",
1565 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1566 &verf,
1567 outgoing_pdu,
1570 return NT_STATUS_OK;
1573 /*******************************************************************
1574 Calculate how much data we're going to send in this packet, also
1575 work out any sign/seal padding length.
1576 ********************************************************************/
1578 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1579 uint32 data_left,
1580 uint16 *p_frag_len,
1581 uint16 *p_auth_len,
1582 uint32 *p_ss_padding)
1584 uint32 data_space, data_len;
1586 switch (cli->auth->auth_level) {
1587 case PIPE_AUTH_LEVEL_NONE:
1588 case PIPE_AUTH_LEVEL_CONNECT:
1589 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1590 data_len = MIN(data_space, data_left);
1591 *p_ss_padding = 0;
1592 *p_auth_len = 0;
1593 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1594 return data_len;
1596 case PIPE_AUTH_LEVEL_INTEGRITY:
1597 case PIPE_AUTH_LEVEL_PRIVACY:
1598 /* Treat the same for all authenticated rpc requests. */
1599 switch(cli->auth->auth_type) {
1600 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1601 case PIPE_AUTH_TYPE_NTLMSSP:
1602 *p_auth_len = NTLMSSP_SIG_SIZE;
1603 break;
1604 case PIPE_AUTH_TYPE_SCHANNEL:
1605 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1606 break;
1607 default:
1608 smb_panic("bad auth type");
1609 break;
1612 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1613 RPC_HDR_AUTH_LEN - *p_auth_len;
1615 data_len = MIN(data_space, data_left);
1616 if (data_len % 8) {
1617 *p_ss_padding = 8 - (data_len % 8);
1619 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1620 data_len + *p_ss_padding + /* data plus padding. */
1621 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1622 return data_len;
1624 default:
1625 smb_panic("bad auth level");
1626 /* Notreached. */
1627 return 0;
1631 /*******************************************************************
1632 External interface.
1633 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1634 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1635 and deals with signing/sealing details.
1636 ********************************************************************/
1638 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1639 uint8 op_num,
1640 prs_struct *in_data,
1641 prs_struct *out_data)
1643 NTSTATUS ret;
1644 uint32 data_left = prs_offset(in_data);
1645 uint32 alloc_hint = prs_offset(in_data);
1646 uint32 data_sent_thistime = 0;
1647 uint32 current_data_offset = 0;
1648 uint32 call_id = get_rpc_call_id();
1649 char pad[8];
1650 prs_struct outgoing_pdu;
1652 memset(pad, '\0', 8);
1654 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1655 /* Server is screwed up ! */
1656 return NT_STATUS_INVALID_PARAMETER;
1659 if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1660 return NT_STATUS_NO_MEMORY;
1662 while (1) {
1663 RPC_HDR hdr;
1664 RPC_HDR_REQ hdr_req;
1665 uint16 auth_len = 0;
1666 uint16 frag_len = 0;
1667 uint8 flags = 0;
1668 uint32 ss_padding = 0;
1670 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1671 &frag_len, &auth_len, &ss_padding);
1673 if (current_data_offset == 0) {
1674 flags = RPC_FLG_FIRST;
1677 if (data_sent_thistime == data_left) {
1678 flags |= RPC_FLG_LAST;
1681 /* Create and marshall the header and request header. */
1682 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1684 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1685 prs_mem_free(&outgoing_pdu);
1686 return NT_STATUS_NO_MEMORY;
1689 /* Create the rpc request RPC_HDR_REQ */
1690 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1692 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1693 prs_mem_free(&outgoing_pdu);
1694 return NT_STATUS_NO_MEMORY;
1697 /* Copy in the data, plus any ss padding. */
1698 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1699 prs_mem_free(&outgoing_pdu);
1700 return NT_STATUS_NO_MEMORY;
1703 /* Copy the sign/seal padding data. */
1704 if (ss_padding) {
1705 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1706 prs_mem_free(&outgoing_pdu);
1707 return NT_STATUS_NO_MEMORY;
1711 /* Generate any auth sign/seal and add the auth footer. */
1712 if (auth_len) {
1713 switch (cli->auth->auth_type) {
1714 case PIPE_AUTH_TYPE_NONE:
1715 break;
1716 case PIPE_AUTH_TYPE_NTLMSSP:
1717 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1718 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1719 if (!NT_STATUS_IS_OK(ret)) {
1720 prs_mem_free(&outgoing_pdu);
1721 return ret;
1723 break;
1724 case PIPE_AUTH_TYPE_SCHANNEL:
1725 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1726 if (!NT_STATUS_IS_OK(ret)) {
1727 prs_mem_free(&outgoing_pdu);
1728 return ret;
1730 break;
1731 default:
1732 smb_panic("bad auth type");
1733 break; /* notreached */
1737 /* Actually send the packet. */
1738 if (flags & RPC_FLG_LAST) {
1739 /* Last packet - send the data, get the reply and return. */
1740 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1741 prs_mem_free(&outgoing_pdu);
1743 if ((DEBUGLEVEL >= 50)
1744 && (cli->transport_type == NCACN_NP)) {
1745 char *dump_name = NULL;
1746 /* Also capture received data */
1747 if (asprintf(&dump_name, "%s/reply_%s_%d",
1748 get_dyn_LOGFILEBASE(),
1749 cli->trans.np.pipe_name, op_num) > 0) {
1750 prs_dump(dump_name, op_num, out_data);
1751 SAFE_FREE(dump_name);
1755 return ret;
1756 } else {
1757 /* More packets to come - write and continue. */
1758 ssize_t num_written;
1760 switch (cli->transport_type) {
1761 case NCACN_NP:
1762 num_written = cli_write(cli->trans.np.cli,
1763 cli->trans.np.fnum,
1764 8, /* 8 means message mode. */
1765 prs_data_p(&outgoing_pdu),
1766 (off_t)0,
1767 (size_t)hdr.frag_len);
1769 if (num_written != hdr.frag_len) {
1770 prs_mem_free(&outgoing_pdu);
1771 return cli_get_nt_error(
1772 cli->trans.np.cli);
1774 break;
1775 case NCACN_IP_TCP:
1776 case NCACN_UNIX_STREAM:
1777 num_written = write_data(
1778 cli->trans.sock.fd,
1779 prs_data_p(&outgoing_pdu),
1780 (size_t)hdr.frag_len);
1781 if (num_written != hdr.frag_len) {
1782 NTSTATUS status;
1783 status = map_nt_error_from_unix(errno);
1784 prs_mem_free(&outgoing_pdu);
1785 return status;
1787 break;
1788 default:
1789 DEBUG(0, ("unknown transport type %d\n",
1790 cli->transport_type));
1791 return NT_STATUS_INTERNAL_ERROR;
1795 current_data_offset += data_sent_thistime;
1796 data_left -= data_sent_thistime;
1798 /* Reset the marshalling position back to zero. */
1799 if (!prs_set_offset(&outgoing_pdu, 0)) {
1800 prs_mem_free(&outgoing_pdu);
1801 return NT_STATUS_NO_MEMORY;
1805 #if 0
1806 /****************************************************************************
1807 Set the handle state.
1808 ****************************************************************************/
1810 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1811 const char *pipe_name, uint16 device_state)
1813 bool state_set = False;
1814 char param[2];
1815 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1816 char *rparam = NULL;
1817 char *rdata = NULL;
1818 uint32 rparam_len, rdata_len;
1820 if (pipe_name == NULL)
1821 return False;
1823 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1824 cli->fnum, pipe_name, device_state));
1826 /* create parameters: device state */
1827 SSVAL(param, 0, device_state);
1829 /* create setup parameters. */
1830 setup[0] = 0x0001;
1831 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1833 /* send the data on \PIPE\ */
1834 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1835 setup, 2, 0, /* setup, length, max */
1836 param, 2, 0, /* param, length, max */
1837 NULL, 0, 1024, /* data, length, max */
1838 &rparam, &rparam_len, /* return param, length */
1839 &rdata, &rdata_len)) /* return data, length */
1841 DEBUG(5, ("Set Handle state: return OK\n"));
1842 state_set = True;
1845 SAFE_FREE(rparam);
1846 SAFE_FREE(rdata);
1848 return state_set;
1850 #endif
1852 /****************************************************************************
1853 Check the rpc bind acknowledge response.
1854 ****************************************************************************/
1856 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1858 if ( hdr_ba->addr.len == 0) {
1859 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1862 /* check the transfer syntax */
1863 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1864 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1865 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1866 return False;
1869 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1870 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1871 hdr_ba->res.num_results, hdr_ba->res.reason));
1874 DEBUG(5,("check_bind_response: accepted!\n"));
1875 return True;
1878 /*******************************************************************
1879 Creates a DCE/RPC bind authentication response.
1880 This is the packet that is sent back to the server once we
1881 have received a BIND-ACK, to finish the third leg of
1882 the authentication handshake.
1883 ********************************************************************/
1885 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1886 uint32 rpc_call_id,
1887 enum pipe_auth_type auth_type,
1888 enum pipe_auth_level auth_level,
1889 DATA_BLOB *pauth_blob,
1890 prs_struct *rpc_out)
1892 RPC_HDR hdr;
1893 RPC_HDR_AUTH hdr_auth;
1894 uint32 pad = 0;
1896 /* Create the request RPC_HDR */
1897 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1898 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1899 pauth_blob->length );
1901 /* Marshall it. */
1902 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1903 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1904 return NT_STATUS_NO_MEMORY;
1908 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1909 about padding - shouldn't this pad to length 8 ? JRA.
1912 /* 4 bytes padding. */
1913 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1914 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1915 return NT_STATUS_NO_MEMORY;
1918 /* Create the request RPC_HDR_AUTHA */
1919 init_rpc_hdr_auth(&hdr_auth,
1920 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1921 auth_level, 0, 1);
1923 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1924 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1925 return NT_STATUS_NO_MEMORY;
1929 * Append the auth data to the outgoing buffer.
1932 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1933 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1934 return NT_STATUS_NO_MEMORY;
1937 return NT_STATUS_OK;
1940 /****************************************************************************
1941 Create and send the third packet in an RPC auth.
1942 ****************************************************************************/
1944 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1945 RPC_HDR *phdr,
1946 prs_struct *rbuf,
1947 uint32 rpc_call_id,
1948 enum pipe_auth_type auth_type,
1949 enum pipe_auth_level auth_level)
1951 DATA_BLOB server_response = data_blob_null;
1952 DATA_BLOB client_reply = data_blob_null;
1953 RPC_HDR_AUTH hdr_auth;
1954 NTSTATUS nt_status;
1955 prs_struct rpc_out;
1956 ssize_t ret;
1958 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1959 return NT_STATUS_INVALID_PARAMETER;
1962 /* Process the returned NTLMSSP blob first. */
1963 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1964 return NT_STATUS_INVALID_PARAMETER;
1967 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1968 return NT_STATUS_INVALID_PARAMETER;
1971 /* TODO - check auth_type/auth_level match. */
1973 server_response = data_blob(NULL, phdr->auth_len);
1974 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1976 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1977 server_response,
1978 &client_reply);
1980 if (!NT_STATUS_IS_OK(nt_status)) {
1981 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1982 data_blob_free(&server_response);
1983 return nt_status;
1986 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1988 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1989 auth_type, auth_level,
1990 &client_reply, &rpc_out);
1992 if (!NT_STATUS_IS_OK(nt_status)) {
1993 prs_mem_free(&rpc_out);
1994 data_blob_free(&client_reply);
1995 data_blob_free(&server_response);
1996 return nt_status;
1999 switch (cli->transport_type) {
2000 case NCACN_NP:
2001 /* 8 here is named pipe message mode. */
2002 ret = cli_write(cli->trans.np.cli, cli->trans.np.fnum,
2003 0x8, prs_data_p(&rpc_out), 0,
2004 (size_t)prs_offset(&rpc_out));
2005 break;
2007 if (ret != (ssize_t)prs_offset(&rpc_out)) {
2008 nt_status = cli_get_nt_error(cli->trans.np.cli);
2010 case NCACN_IP_TCP:
2011 case NCACN_UNIX_STREAM:
2012 ret = write_data(cli->trans.sock.fd, prs_data_p(&rpc_out),
2013 (size_t)prs_offset(&rpc_out));
2014 if (ret != (ssize_t)prs_offset(&rpc_out)) {
2015 nt_status = map_nt_error_from_unix(errno);
2017 break;
2018 default:
2019 DEBUG(0, ("unknown transport type %d\n", cli->transport_type));
2020 return NT_STATUS_INTERNAL_ERROR;
2023 if (ret != (ssize_t)prs_offset(&rpc_out)) {
2024 DEBUG(0,("rpc_send_auth_auth3: write failed. Return was %s\n",
2025 nt_errstr(nt_status)));
2026 prs_mem_free(&rpc_out);
2027 data_blob_free(&client_reply);
2028 data_blob_free(&server_response);
2029 return nt_status;
2032 DEBUG(5,("rpc_send_auth_auth3: %s sent auth3 response ok.\n",
2033 rpccli_pipe_txt(debug_ctx(), cli)));
2035 prs_mem_free(&rpc_out);
2036 data_blob_free(&client_reply);
2037 data_blob_free(&server_response);
2038 return NT_STATUS_OK;
2041 /*******************************************************************
2042 Creates a DCE/RPC bind alter context authentication request which
2043 may contain a spnego auth blobl
2044 ********************************************************************/
2046 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2047 const RPC_IFACE *abstract,
2048 const RPC_IFACE *transfer,
2049 enum pipe_auth_level auth_level,
2050 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2051 prs_struct *rpc_out)
2053 RPC_HDR_AUTH hdr_auth;
2054 prs_struct auth_info;
2055 NTSTATUS ret = NT_STATUS_OK;
2057 ZERO_STRUCT(hdr_auth);
2058 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2059 return NT_STATUS_NO_MEMORY;
2061 /* We may change the pad length before marshalling. */
2062 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
2064 if (pauth_blob->length) {
2065 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2066 prs_mem_free(&auth_info);
2067 return NT_STATUS_NO_MEMORY;
2071 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
2072 rpc_out,
2073 rpc_call_id,
2074 abstract,
2075 transfer,
2076 &hdr_auth,
2077 &auth_info);
2078 prs_mem_free(&auth_info);
2079 return ret;
2082 /*******************************************************************
2083 Third leg of the SPNEGO bind mechanism - sends alter context PDU
2084 and gets a response.
2085 ********************************************************************/
2087 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
2088 RPC_HDR *phdr,
2089 prs_struct *rbuf,
2090 uint32 rpc_call_id,
2091 const RPC_IFACE *abstract,
2092 const RPC_IFACE *transfer,
2093 enum pipe_auth_type auth_type,
2094 enum pipe_auth_level auth_level)
2096 DATA_BLOB server_spnego_response = data_blob_null;
2097 DATA_BLOB server_ntlm_response = data_blob_null;
2098 DATA_BLOB client_reply = data_blob_null;
2099 DATA_BLOB tmp_blob = data_blob_null;
2100 RPC_HDR_AUTH hdr_auth;
2101 NTSTATUS nt_status;
2102 prs_struct rpc_out;
2104 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2105 return NT_STATUS_INVALID_PARAMETER;
2108 /* Process the returned NTLMSSP blob first. */
2109 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2110 return NT_STATUS_INVALID_PARAMETER;
2113 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2114 return NT_STATUS_INVALID_PARAMETER;
2117 server_spnego_response = data_blob(NULL, phdr->auth_len);
2118 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2120 /* The server might give us back two challenges - tmp_blob is for the second. */
2121 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
2122 data_blob_free(&server_spnego_response);
2123 data_blob_free(&server_ntlm_response);
2124 data_blob_free(&tmp_blob);
2125 return NT_STATUS_INVALID_PARAMETER;
2128 /* We're finished with the server spnego response and the tmp_blob. */
2129 data_blob_free(&server_spnego_response);
2130 data_blob_free(&tmp_blob);
2132 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
2133 server_ntlm_response,
2134 &client_reply);
2136 /* Finished with the server_ntlm response */
2137 data_blob_free(&server_ntlm_response);
2139 if (!NT_STATUS_IS_OK(nt_status)) {
2140 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
2141 data_blob_free(&client_reply);
2142 return nt_status;
2145 /* SPNEGO wrap the client reply. */
2146 tmp_blob = spnego_gen_auth(client_reply);
2147 data_blob_free(&client_reply);
2148 client_reply = tmp_blob;
2149 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
2151 /* Now prepare the alter context pdu. */
2152 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
2154 nt_status = create_rpc_alter_context(rpc_call_id,
2155 abstract,
2156 transfer,
2157 auth_level,
2158 &client_reply,
2159 &rpc_out);
2161 data_blob_free(&client_reply);
2163 if (!NT_STATUS_IS_OK(nt_status)) {
2164 prs_mem_free(&rpc_out);
2165 return nt_status;
2168 /* Initialize the returning data struct. */
2169 prs_mem_free(rbuf);
2170 prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
2172 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
2173 if (!NT_STATUS_IS_OK(nt_status)) {
2174 prs_mem_free(&rpc_out);
2175 return nt_status;
2178 prs_mem_free(&rpc_out);
2180 /* Get the auth blob from the reply. */
2181 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
2182 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
2183 return NT_STATUS_BUFFER_TOO_SMALL;
2186 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2187 return NT_STATUS_INVALID_PARAMETER;
2190 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2191 return NT_STATUS_INVALID_PARAMETER;
2194 server_spnego_response = data_blob(NULL, phdr->auth_len);
2195 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2197 /* Check we got a valid auth response. */
2198 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
2199 data_blob_free(&server_spnego_response);
2200 data_blob_free(&tmp_blob);
2201 return NT_STATUS_INVALID_PARAMETER;
2204 data_blob_free(&server_spnego_response);
2205 data_blob_free(&tmp_blob);
2207 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2208 "%s.\n", rpccli_pipe_txt(debug_ctx(), cli)));
2210 return NT_STATUS_OK;
2213 /****************************************************************************
2214 Do an rpc bind.
2215 ****************************************************************************/
2217 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2218 struct cli_pipe_auth_data *auth)
2220 RPC_HDR hdr;
2221 RPC_HDR_BA hdr_ba;
2222 prs_struct rpc_out;
2223 prs_struct rbuf;
2224 uint32 rpc_call_id;
2225 NTSTATUS status;
2227 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2228 rpccli_pipe_txt(debug_ctx(), cli),
2229 (unsigned int)auth->auth_type,
2230 (unsigned int)auth->auth_level ));
2232 cli->auth = talloc_move(cli, &auth);
2234 prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2236 rpc_call_id = get_rpc_call_id();
2238 /* Marshall the outgoing data. */
2239 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2240 &cli->abstract_syntax,
2241 &cli->transfer_syntax,
2242 cli->auth->auth_type,
2243 cli->auth->auth_level);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 prs_mem_free(&rpc_out);
2247 return status;
2250 /* Initialize the incoming data struct. */
2251 prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2253 /* send data on \PIPE\. receive a response */
2254 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 prs_mem_free(&rpc_out);
2257 return status;
2260 prs_mem_free(&rpc_out);
2262 DEBUG(3,("rpc_pipe_bind: %s bind request returned ok.\n",
2263 rpccli_pipe_txt(debug_ctx(), cli)));
2265 /* Unmarshall the RPC header */
2266 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2267 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2268 prs_mem_free(&rbuf);
2269 return NT_STATUS_BUFFER_TOO_SMALL;
2272 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2273 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2274 prs_mem_free(&rbuf);
2275 return NT_STATUS_BUFFER_TOO_SMALL;
2278 if(!check_bind_response(&hdr_ba, &cli->transfer_syntax)) {
2279 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2280 prs_mem_free(&rbuf);
2281 return NT_STATUS_BUFFER_TOO_SMALL;
2284 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2285 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2287 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2288 switch(cli->auth->auth_type) {
2290 case PIPE_AUTH_TYPE_NONE:
2291 case PIPE_AUTH_TYPE_SCHANNEL:
2292 /* Bind complete. */
2293 break;
2295 case PIPE_AUTH_TYPE_NTLMSSP:
2296 /* Need to send AUTH3 packet - no reply. */
2297 status = rpc_finish_auth3_bind(
2298 cli, &hdr, &rbuf, rpc_call_id,
2299 cli->auth->auth_type,
2300 cli->auth->auth_level);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 prs_mem_free(&rbuf);
2303 return status;
2305 break;
2307 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2308 /* Need to send alter context request and reply. */
2309 status = rpc_finish_spnego_ntlmssp_bind(
2310 cli, &hdr, &rbuf, rpc_call_id,
2311 &cli->abstract_syntax, &cli->transfer_syntax,
2312 cli->auth->auth_type, cli->auth->auth_level);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 prs_mem_free(&rbuf);
2315 return status;
2317 break;
2319 case PIPE_AUTH_TYPE_KRB5:
2320 /* */
2322 default:
2323 DEBUG(0,("cli_finish_bind_auth: unknown auth type "
2324 "%u\n", (unsigned int)cli->auth->auth_type));
2325 prs_mem_free(&rbuf);
2326 return NT_STATUS_INVALID_INFO_CLASS;
2329 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2330 if (cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP
2331 || cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2332 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2333 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2334 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2335 prs_mem_free(&rbuf);
2336 return NT_STATUS_INVALID_PARAMETER;
2339 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2340 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2341 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2342 prs_mem_free(&rbuf);
2343 return NT_STATUS_INVALID_PARAMETER;
2348 prs_mem_free(&rbuf);
2349 return NT_STATUS_OK;
2352 unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
2353 unsigned int timeout)
2355 return cli_set_timeout(cli->trans.np.cli, timeout);
2358 bool rpccli_is_pipe_idx(struct rpc_pipe_client *cli, int pipe_idx)
2360 return ndr_syntax_id_equal(&cli->abstract_syntax,
2361 pipe_names[pipe_idx].abstr_syntax);
2364 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16])
2366 if ((cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2367 || (cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2368 memcpy(nt_hash, cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2369 return true;
2372 if (cli->transport_type == NCACN_NP) {
2373 E_md4hash(cli->trans.np.cli->pwd.password, nt_hash);
2374 return true;
2377 return false;
2380 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
2382 if (p->transport_type == NCACN_NP) {
2383 return p->trans.np.cli;
2385 return NULL;
2388 static int rpc_pipe_destructor(struct rpc_pipe_client *p)
2390 if (p->transport_type == NCACN_NP) {
2391 bool ret;
2392 ret = cli_close(p->trans.np.cli, p->trans.np.fnum);
2393 if (!ret) {
2394 DEBUG(1, ("rpc_pipe_destructor: cli_close failed on "
2395 "pipe %s. Error was %s\n",
2396 rpccli_pipe_txt(debug_ctx(), p),
2397 cli_errstr(p->trans.np.cli)));
2400 DEBUG(10, ("rpc_pipe_destructor: closed %s\n",
2401 rpccli_pipe_txt(debug_ctx(), p)));
2403 DLIST_REMOVE(p->trans.np.cli->pipe_list, p);
2404 return ret ? -1 : 0;
2407 return -1;
2410 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2411 struct cli_pipe_auth_data **presult)
2413 struct cli_pipe_auth_data *result;
2415 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2416 if (result == NULL) {
2417 return NT_STATUS_NO_MEMORY;
2420 result->auth_type = PIPE_AUTH_TYPE_NONE;
2421 result->auth_level = PIPE_AUTH_LEVEL_NONE;
2423 result->user_name = talloc_strdup(result, "");
2424 result->domain = talloc_strdup(result, "");
2425 if ((result->user_name == NULL) || (result->domain == NULL)) {
2426 TALLOC_FREE(result);
2427 return NT_STATUS_NO_MEMORY;
2430 *presult = result;
2431 return NT_STATUS_OK;
2434 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2436 ntlmssp_end(&auth->a_u.ntlmssp_state);
2437 return 0;
2440 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2441 enum pipe_auth_type auth_type,
2442 enum pipe_auth_level auth_level,
2443 const char *domain,
2444 const char *username,
2445 const char *password,
2446 struct cli_pipe_auth_data **presult)
2448 struct cli_pipe_auth_data *result;
2449 NTSTATUS status;
2451 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2452 if (result == NULL) {
2453 return NT_STATUS_NO_MEMORY;
2456 result->auth_type = auth_type;
2457 result->auth_level = auth_level;
2459 result->user_name = talloc_strdup(result, username);
2460 result->domain = talloc_strdup(result, domain);
2461 if ((result->user_name == NULL) || (result->domain == NULL)) {
2462 status = NT_STATUS_NO_MEMORY;
2463 goto fail;
2466 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 goto fail;
2471 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2473 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2474 if (!NT_STATUS_IS_OK(status)) {
2475 goto fail;
2478 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 goto fail;
2483 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 goto fail;
2489 * Turn off sign+seal to allow selected auth level to turn it back on.
2491 result->a_u.ntlmssp_state->neg_flags &=
2492 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2494 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2495 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2496 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2497 result->a_u.ntlmssp_state->neg_flags
2498 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2501 *presult = result;
2502 return NT_STATUS_OK;
2504 fail:
2505 TALLOC_FREE(result);
2506 return status;
2509 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2510 enum pipe_auth_level auth_level,
2511 const uint8_t sess_key[16],
2512 struct cli_pipe_auth_data **presult)
2514 struct cli_pipe_auth_data *result;
2516 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2517 if (result == NULL) {
2518 return NT_STATUS_NO_MEMORY;
2521 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2522 result->auth_level = auth_level;
2524 result->user_name = talloc_strdup(result, "");
2525 result->domain = talloc_strdup(result, domain);
2526 if ((result->user_name == NULL) || (result->domain == NULL)) {
2527 goto fail;
2530 result->a_u.schannel_auth = talloc(result,
2531 struct schannel_auth_struct);
2532 if (result->a_u.schannel_auth == NULL) {
2533 goto fail;
2536 memcpy(result->a_u.schannel_auth->sess_key, sess_key,
2537 sizeof(result->a_u.schannel_auth->sess_key));
2538 result->a_u.schannel_auth->seq_num = 0;
2540 *presult = result;
2541 return NT_STATUS_OK;
2543 fail:
2544 TALLOC_FREE(result);
2545 return NT_STATUS_NO_MEMORY;
2548 #ifdef HAVE_KRB5
2549 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2551 data_blob_free(&auth->session_key);
2552 return 0;
2554 #endif
2556 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2557 enum pipe_auth_level auth_level,
2558 const char *service_princ,
2559 const char *username,
2560 const char *password,
2561 struct cli_pipe_auth_data **presult)
2563 #ifdef HAVE_KRB5
2564 struct cli_pipe_auth_data *result;
2566 if ((username != NULL) && (password != NULL)) {
2567 int ret = kerberos_kinit_password(username, password, 0, NULL);
2568 if (ret != 0) {
2569 return NT_STATUS_ACCESS_DENIED;
2573 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2574 if (result == NULL) {
2575 return NT_STATUS_NO_MEMORY;
2578 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2579 result->auth_level = auth_level;
2582 * Username / domain need fixing!
2584 result->user_name = talloc_strdup(result, "");
2585 result->domain = talloc_strdup(result, "");
2586 if ((result->user_name == NULL) || (result->domain == NULL)) {
2587 goto fail;
2590 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2591 result, struct kerberos_auth_struct);
2592 if (result->a_u.kerberos_auth == NULL) {
2593 goto fail;
2595 talloc_set_destructor(result->a_u.kerberos_auth,
2596 cli_auth_kerberos_data_destructor);
2598 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2599 result, service_princ);
2600 if (result->a_u.kerberos_auth->service_principal == NULL) {
2601 goto fail;
2604 *presult = result;
2605 return NT_STATUS_OK;
2607 fail:
2608 TALLOC_FREE(result);
2609 return NT_STATUS_NO_MEMORY;
2610 #else
2611 return NT_STATUS_NOT_SUPPORTED;
2612 #endif
2615 static int rpc_pipe_sock_destructor(struct rpc_pipe_client *p)
2617 close(p->trans.sock.fd);
2618 return 0;
2622 * Create an rpc pipe client struct, connecting to a tcp port.
2624 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2625 uint16_t port,
2626 const struct ndr_syntax_id *abstract_syntax,
2627 struct rpc_pipe_client **presult)
2629 struct rpc_pipe_client *result;
2630 struct sockaddr_storage addr;
2631 NTSTATUS status;
2633 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2634 if (result == NULL) {
2635 return NT_STATUS_NO_MEMORY;
2638 result->transport_type = NCACN_IP_TCP;
2640 result->abstract_syntax = *abstract_syntax;
2641 result->transfer_syntax = ndr_transfer_syntax;
2643 result->desthost = talloc_strdup(result, host);
2644 result->srv_name_slash = talloc_asprintf_strupper_m(
2645 result, "\\\\%s", result->desthost);
2646 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2647 status = NT_STATUS_NO_MEMORY;
2648 goto fail;
2651 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2652 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2654 if (!resolve_name(host, &addr, 0)) {
2655 status = NT_STATUS_NOT_FOUND;
2656 goto fail;
2659 result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60);
2660 if (result->trans.sock.fd == -1) {
2661 status = map_nt_error_from_unix(errno);
2662 goto fail;
2665 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2667 *presult = result;
2668 return NT_STATUS_OK;
2670 fail:
2671 TALLOC_FREE(result);
2672 return status;
2676 * Determine the tcp port on which a dcerpc interface is listening
2677 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2678 * target host.
2680 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2681 const struct ndr_syntax_id *abstract_syntax,
2682 uint16_t *pport)
2684 NTSTATUS status;
2685 struct rpc_pipe_client *epm_pipe = NULL;
2686 struct cli_pipe_auth_data *auth = NULL;
2687 struct dcerpc_binding *map_binding = NULL;
2688 struct dcerpc_binding *res_binding = NULL;
2689 struct epm_twr_t *map_tower = NULL;
2690 struct epm_twr_t *res_towers = NULL;
2691 struct policy_handle *entry_handle = NULL;
2692 uint32_t num_towers = 0;
2693 uint32_t max_towers = 1;
2694 struct epm_twr_p_t towers;
2695 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2697 if (pport == NULL) {
2698 status = NT_STATUS_INVALID_PARAMETER;
2699 goto done;
2702 /* open the connection to the endpoint mapper */
2703 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2704 &ndr_table_epmapper.syntax_id,
2705 &epm_pipe);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 goto done;
2711 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2712 if (!NT_STATUS_IS_OK(status)) {
2713 goto done;
2716 status = rpc_pipe_bind(epm_pipe, auth);
2717 if (!NT_STATUS_IS_OK(status)) {
2718 goto done;
2721 /* create tower for asking the epmapper */
2723 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2724 if (map_binding == NULL) {
2725 status = NT_STATUS_NO_MEMORY;
2726 goto done;
2729 map_binding->transport = NCACN_IP_TCP;
2730 map_binding->object = *abstract_syntax;
2731 map_binding->host = host; /* needed? */
2732 map_binding->endpoint = "0"; /* correct? needed? */
2734 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2735 if (map_tower == NULL) {
2736 status = NT_STATUS_NO_MEMORY;
2737 goto done;
2740 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2741 &(map_tower->tower));
2742 if (!NT_STATUS_IS_OK(status)) {
2743 goto done;
2746 /* allocate further parameters for the epm_Map call */
2748 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2749 if (res_towers == NULL) {
2750 status = NT_STATUS_NO_MEMORY;
2751 goto done;
2753 towers.twr = res_towers;
2755 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2756 if (entry_handle == NULL) {
2757 status = NT_STATUS_NO_MEMORY;
2758 goto done;
2761 /* ask the endpoint mapper for the port */
2763 status = rpccli_epm_Map(epm_pipe,
2764 tmp_ctx,
2765 CONST_DISCARD(struct GUID *,
2766 &(abstract_syntax->uuid)),
2767 map_tower,
2768 entry_handle,
2769 max_towers,
2770 &num_towers,
2771 &towers);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 goto done;
2777 if (num_towers != 1) {
2778 status = NT_STATUS_UNSUCCESSFUL;
2779 goto done;
2782 /* extract the port from the answer */
2784 status = dcerpc_binding_from_tower(tmp_ctx,
2785 &(towers.twr->tower),
2786 &res_binding);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 goto done;
2791 /* are further checks here necessary? */
2792 if (res_binding->transport != NCACN_IP_TCP) {
2793 status = NT_STATUS_UNSUCCESSFUL;
2794 goto done;
2797 *pport = (uint16_t)atoi(res_binding->endpoint);
2799 done:
2800 TALLOC_FREE(tmp_ctx);
2801 return status;
2805 * Create a rpc pipe client struct, connecting to a host via tcp.
2806 * The port is determined by asking the endpoint mapper on the given
2807 * host.
2809 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2810 const struct ndr_syntax_id *abstract_syntax,
2811 struct rpc_pipe_client **presult)
2813 NTSTATUS status;
2814 uint16_t port = 0;
2816 *presult = NULL;
2818 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 goto done;
2823 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
2824 abstract_syntax, presult);
2826 done:
2827 return status;
2830 /********************************************************************
2831 Create a rpc pipe client struct, connecting to a unix domain socket
2832 ********************************************************************/
2833 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2834 const struct ndr_syntax_id *abstract_syntax,
2835 struct rpc_pipe_client **presult)
2837 struct rpc_pipe_client *result;
2838 struct sockaddr_un addr;
2839 NTSTATUS status;
2841 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2842 if (result == NULL) {
2843 return NT_STATUS_NO_MEMORY;
2846 result->transport_type = NCACN_UNIX_STREAM;
2848 result->abstract_syntax = *abstract_syntax;
2849 result->transfer_syntax = ndr_transfer_syntax;
2851 result->desthost = get_myname(result);
2852 result->srv_name_slash = talloc_asprintf_strupper_m(
2853 result, "\\\\%s", result->desthost);
2854 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2855 status = NT_STATUS_NO_MEMORY;
2856 goto fail;
2859 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2860 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2862 result->trans.sock.fd = socket(AF_UNIX, SOCK_STREAM, 0);
2863 if (result->trans.sock.fd == -1) {
2864 status = map_nt_error_from_unix(errno);
2865 goto fail;
2868 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2870 ZERO_STRUCT(addr);
2871 addr.sun_family = AF_UNIX;
2872 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2874 if (sys_connect(result->trans.sock.fd,
2875 (struct sockaddr *)&addr) == -1) {
2876 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2877 strerror(errno)));
2878 close(result->trans.sock.fd);
2879 return map_nt_error_from_unix(errno);
2882 *presult = result;
2883 return NT_STATUS_OK;
2885 fail:
2886 TALLOC_FREE(result);
2887 return status;
2891 /****************************************************************************
2892 Open a named pipe over SMB to a remote server.
2894 * CAVEAT CALLER OF THIS FUNCTION:
2895 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2896 * so be sure that this function is called AFTER any structure (vs pointer)
2897 * assignment of the cli. In particular, libsmbclient does structure
2898 * assignments of cli, which invalidates the data in the returned
2899 * rpc_pipe_client if this function is called before the structure assignment
2900 * of cli.
2902 ****************************************************************************/
2904 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2905 const struct ndr_syntax_id *abstract_syntax,
2906 struct rpc_pipe_client **presult)
2908 struct rpc_pipe_client *result;
2909 int fnum;
2911 /* sanity check to protect against crashes */
2913 if ( !cli ) {
2914 return NT_STATUS_INVALID_HANDLE;
2917 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2918 if (result == NULL) {
2919 return NT_STATUS_NO_MEMORY;
2922 result->transport_type = NCACN_NP;
2924 result->trans.np.pipe_name = cli_get_pipe_name_from_iface(
2925 result, cli, abstract_syntax);
2926 if (result->trans.np.pipe_name == NULL) {
2927 DEBUG(1, ("Could not find pipe for interface\n"));
2928 TALLOC_FREE(result);
2929 return NT_STATUS_INVALID_PARAMETER;
2932 result->trans.np.cli = cli;
2933 result->abstract_syntax = *abstract_syntax;
2934 result->transfer_syntax = ndr_transfer_syntax;
2935 result->desthost = talloc_strdup(result, cli->desthost);
2936 result->srv_name_slash = talloc_asprintf_strupper_m(
2937 result, "\\\\%s", result->desthost);
2939 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2940 TALLOC_FREE(result);
2941 return NT_STATUS_NO_MEMORY;
2944 fnum = cli_nt_create(cli, result->trans.np.pipe_name,
2945 DESIRED_ACCESS_PIPE);
2946 if (fnum == -1) {
2947 DEBUG(1,("rpc_pipe_open_np: cli_nt_create failed on pipe %s "
2948 "to machine %s. Error was %s\n",
2949 result->trans.np.pipe_name, cli->desthost,
2950 cli_errstr(cli)));
2951 TALLOC_FREE(result);
2952 return cli_get_nt_error(cli);
2955 result->trans.np.fnum = fnum;
2957 DLIST_ADD(cli->pipe_list, result);
2958 talloc_set_destructor(result, rpc_pipe_destructor);
2960 *presult = result;
2961 return NT_STATUS_OK;
2964 /****************************************************************************
2965 Open a pipe to a remote server.
2966 ****************************************************************************/
2968 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2969 const struct ndr_syntax_id *interface,
2970 struct rpc_pipe_client **presult)
2972 if (ndr_syntax_id_equal(interface, &ndr_table_drsuapi.syntax_id)) {
2974 * We should have a better way to figure out this drsuapi
2975 * speciality...
2977 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2978 presult);
2981 return rpc_pipe_open_np(cli, interface, presult);
2984 /****************************************************************************
2985 Open a named pipe to an SMB server and bind anonymously.
2986 ****************************************************************************/
2988 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2989 const struct ndr_syntax_id *interface,
2990 struct rpc_pipe_client **presult)
2992 struct rpc_pipe_client *result;
2993 struct cli_pipe_auth_data *auth;
2994 NTSTATUS status;
2996 status = cli_rpc_pipe_open(cli, interface, &result);
2997 if (!NT_STATUS_IS_OK(status)) {
2998 return status;
3001 status = rpccli_anon_bind_data(result, &auth);
3002 if (!NT_STATUS_IS_OK(status)) {
3003 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3004 nt_errstr(status)));
3005 TALLOC_FREE(result);
3006 return status;
3010 * This is a bit of an abstraction violation due to the fact that an
3011 * anonymous bind on an authenticated SMB inherits the user/domain
3012 * from the enclosing SMB creds
3015 TALLOC_FREE(auth->user_name);
3016 TALLOC_FREE(auth->domain);
3018 auth->user_name = talloc_strdup(auth, cli->user_name);
3019 auth->domain = talloc_strdup(auth, cli->domain);
3021 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3022 TALLOC_FREE(result);
3023 return NT_STATUS_NO_MEMORY;
3026 status = rpc_pipe_bind(result, auth);
3027 if (!NT_STATUS_IS_OK(status)) {
3028 int lvl = 0;
3029 if (ndr_syntax_id_equal(interface,
3030 &ndr_table_dssetup.syntax_id)) {
3031 /* non AD domains just don't have this pipe, avoid
3032 * level 0 statement in that case - gd */
3033 lvl = 3;
3035 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3036 "%s failed with error %s\n",
3037 cli_get_pipe_name_from_iface(debug_ctx(), cli,
3038 interface),
3039 nt_errstr(status) ));
3040 TALLOC_FREE(result);
3041 return status;
3044 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3045 "%s and bound anonymously.\n", result->trans.np.pipe_name,
3046 cli->desthost ));
3048 *presult = result;
3049 return NT_STATUS_OK;
3052 /****************************************************************************
3053 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3054 ****************************************************************************/
3056 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3057 const struct ndr_syntax_id *interface,
3058 enum pipe_auth_type auth_type,
3059 enum pipe_auth_level auth_level,
3060 const char *domain,
3061 const char *username,
3062 const char *password,
3063 struct rpc_pipe_client **presult)
3065 struct rpc_pipe_client *result;
3066 struct cli_pipe_auth_data *auth;
3067 NTSTATUS status;
3069 status = cli_rpc_pipe_open(cli, interface, &result);
3070 if (!NT_STATUS_IS_OK(status)) {
3071 return status;
3074 status = rpccli_ntlmssp_bind_data(
3075 result, auth_type, auth_level, domain, username,
3076 cli->pwd.null_pwd ? NULL : password, &auth);
3077 if (!NT_STATUS_IS_OK(status)) {
3078 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3079 nt_errstr(status)));
3080 goto err;
3083 status = rpc_pipe_bind(result, auth);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3086 nt_errstr(status) ));
3087 goto err;
3090 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3091 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3092 result->trans.np.pipe_name, cli->desthost,
3093 domain, username ));
3095 *presult = result;
3096 return NT_STATUS_OK;
3098 err:
3100 TALLOC_FREE(result);
3101 return status;
3104 /****************************************************************************
3105 External interface.
3106 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3107 ****************************************************************************/
3109 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3110 const struct ndr_syntax_id *interface,
3111 enum pipe_auth_level auth_level,
3112 const char *domain,
3113 const char *username,
3114 const char *password,
3115 struct rpc_pipe_client **presult)
3117 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3118 interface,
3119 PIPE_AUTH_TYPE_NTLMSSP,
3120 auth_level,
3121 domain,
3122 username,
3123 password,
3124 presult);
3127 /****************************************************************************
3128 External interface.
3129 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3130 ****************************************************************************/
3132 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3133 const struct ndr_syntax_id *interface,
3134 enum pipe_auth_level auth_level,
3135 const char *domain,
3136 const char *username,
3137 const char *password,
3138 struct rpc_pipe_client **presult)
3140 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3141 interface,
3142 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3143 auth_level,
3144 domain,
3145 username,
3146 password,
3147 presult);
3150 /****************************************************************************
3151 Get a the schannel session key out of an already opened netlogon pipe.
3152 ****************************************************************************/
3153 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3154 struct cli_state *cli,
3155 const char *domain,
3156 uint32 *pneg_flags)
3158 uint32 sec_chan_type = 0;
3159 unsigned char machine_pwd[16];
3160 const char *machine_account;
3161 NTSTATUS status;
3163 /* Get the machine account credentials from secrets.tdb. */
3164 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3165 &sec_chan_type))
3167 DEBUG(0, ("get_schannel_session_key: could not fetch "
3168 "trust account password for domain '%s'\n",
3169 domain));
3170 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3173 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3174 cli->desthost, /* server name */
3175 domain, /* domain */
3176 global_myname(), /* client name */
3177 machine_account, /* machine account name */
3178 machine_pwd,
3179 sec_chan_type,
3180 pneg_flags);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 DEBUG(3, ("get_schannel_session_key_common: "
3184 "rpccli_netlogon_setup_creds failed with result %s "
3185 "to server %s, domain %s, machine account %s.\n",
3186 nt_errstr(status), cli->desthost, domain,
3187 machine_account ));
3188 return status;
3191 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3192 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3193 cli->desthost));
3194 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3197 return NT_STATUS_OK;;
3200 /****************************************************************************
3201 Open a netlogon pipe and get the schannel session key.
3202 Now exposed to external callers.
3203 ****************************************************************************/
3206 struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
3207 const char *domain,
3208 uint32 *pneg_flags,
3209 NTSTATUS *perr)
3211 struct rpc_pipe_client *netlogon_pipe = NULL;
3213 *perr = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3214 &netlogon_pipe);
3215 if (!NT_STATUS_IS_OK(*perr)) {
3216 return NULL;
3219 *perr = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3220 pneg_flags);
3221 if (!NT_STATUS_IS_OK(*perr)) {
3222 TALLOC_FREE(netlogon_pipe);
3223 return NULL;
3226 return netlogon_pipe;
3229 /****************************************************************************
3230 External interface.
3231 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3232 using session_key. sign and seal.
3233 ****************************************************************************/
3235 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3236 int pipe_idx,
3237 enum pipe_auth_level auth_level,
3238 const char *domain,
3239 const struct dcinfo *pdc,
3240 NTSTATUS *perr)
3242 struct rpc_pipe_client *result;
3243 struct cli_pipe_auth_data *auth;
3245 *perr = cli_rpc_pipe_open(cli, pipe_names[pipe_idx].abstr_syntax,
3246 &result);
3247 if (!NT_STATUS_IS_OK(*perr)) {
3248 return NULL;
3251 *perr = rpccli_schannel_bind_data(result, domain, auth_level,
3252 pdc->sess_key, &auth);
3253 if (!NT_STATUS_IS_OK(*perr)) {
3254 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3255 nt_errstr(*perr)));
3256 TALLOC_FREE(result);
3257 return NULL;
3260 *perr = rpc_pipe_bind(result, auth);
3261 if (!NT_STATUS_IS_OK(*perr)) {
3262 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
3263 nt_errstr(*perr) ));
3264 TALLOC_FREE(result);
3265 return NULL;
3269 * The credentials on a new netlogon pipe are the ones we are passed
3270 * in - copy them over.
3272 result->dc = (struct dcinfo *)talloc_memdup(result, pdc, sizeof(*pdc));
3273 if (result->dc == NULL) {
3274 DEBUG(0, ("talloc failed\n"));
3275 TALLOC_FREE(result);
3276 return NULL;
3279 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3280 "for domain %s "
3281 "and bound using schannel.\n",
3282 result->trans.np.pipe_name, cli->desthost, domain ));
3284 return result;
3287 /****************************************************************************
3288 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3289 Fetch the session key ourselves using a temporary netlogon pipe. This
3290 version uses an ntlmssp auth bound netlogon pipe to get the key.
3291 ****************************************************************************/
3293 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3294 const char *domain,
3295 const char *username,
3296 const char *password,
3297 uint32 *pneg_flags,
3298 NTSTATUS *perr)
3300 struct rpc_pipe_client *netlogon_pipe = NULL;
3302 *perr = cli_rpc_pipe_open_spnego_ntlmssp(cli,
3303 &ndr_table_netlogon.syntax_id,
3304 PIPE_AUTH_LEVEL_PRIVACY,
3305 domain, username, password,
3306 &netlogon_pipe);
3307 if (!netlogon_pipe) {
3308 return NULL;
3311 *perr = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3312 pneg_flags);
3313 if (!NT_STATUS_IS_OK(*perr)) {
3314 TALLOC_FREE(netlogon_pipe);
3315 return NULL;
3318 return netlogon_pipe;
3321 /****************************************************************************
3322 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3323 Fetch the session key ourselves using a temporary netlogon pipe. This version
3324 uses an ntlmssp bind to get the session key.
3325 ****************************************************************************/
3327 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3328 int pipe_idx,
3329 enum pipe_auth_level auth_level,
3330 const char *domain,
3331 const char *username,
3332 const char *password,
3333 NTSTATUS *perr)
3335 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3336 struct rpc_pipe_client *netlogon_pipe = NULL;
3337 struct rpc_pipe_client *result = NULL;
3339 netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
3340 password, &neg_flags, perr);
3341 if (!netlogon_pipe) {
3342 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3343 "key from server %s for domain %s.\n",
3344 cli->desthost, domain ));
3345 return NULL;
3348 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
3349 auth_level,
3350 domain, netlogon_pipe->dc, perr);
3352 /* Now we've bound using the session key we can close the netlog pipe. */
3353 TALLOC_FREE(netlogon_pipe);
3355 return result;
3358 /****************************************************************************
3359 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3360 Fetch the session key ourselves using a temporary netlogon pipe.
3361 ****************************************************************************/
3363 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
3364 int pipe_idx,
3365 enum pipe_auth_level auth_level,
3366 const char *domain,
3367 NTSTATUS *perr)
3369 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3370 struct rpc_pipe_client *netlogon_pipe = NULL;
3371 struct rpc_pipe_client *result = NULL;
3373 netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
3374 if (!netlogon_pipe) {
3375 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3376 "key from server %s for domain %s.\n",
3377 cli->desthost, domain ));
3378 return NULL;
3381 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
3382 auth_level,
3383 domain, netlogon_pipe->dc, perr);
3385 /* Now we've bound using the session key we can close the netlog pipe. */
3386 TALLOC_FREE(netlogon_pipe);
3388 return result;
3391 /****************************************************************************
3392 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3393 The idea is this can be called with service_princ, username and password all
3394 NULL so long as the caller has a TGT.
3395 ****************************************************************************/
3397 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
3398 int pipe_idx,
3399 enum pipe_auth_level auth_level,
3400 const char *service_princ,
3401 const char *username,
3402 const char *password,
3403 NTSTATUS *perr)
3405 #ifdef HAVE_KRB5
3406 struct rpc_pipe_client *result;
3407 struct cli_pipe_auth_data *auth;
3409 *perr = cli_rpc_pipe_open(cli, pipe_names[pipe_idx].abstr_syntax,
3410 &result);
3411 if (!NT_STATUS_IS_OK(*perr)) {
3412 return NULL;
3415 *perr = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3416 username, password, &auth);
3417 if (!NT_STATUS_IS_OK(*perr)) {
3418 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3419 nt_errstr(*perr)));
3420 TALLOC_FREE(result);
3421 return NULL;
3424 *perr = rpc_pipe_bind(result, auth);
3425 if (!NT_STATUS_IS_OK(*perr)) {
3426 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
3427 nt_errstr(*perr) ));
3428 TALLOC_FREE(result);
3429 return NULL;
3432 return result;
3433 #else
3434 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3435 return NULL;
3436 #endif
3439 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3440 struct rpc_pipe_client *cli,
3441 DATA_BLOB *session_key)
3443 if (!session_key || !cli) {
3444 return NT_STATUS_INVALID_PARAMETER;
3447 if (!cli->auth) {
3448 return NT_STATUS_INVALID_PARAMETER;
3451 switch (cli->auth->auth_type) {
3452 case PIPE_AUTH_TYPE_SCHANNEL:
3453 *session_key = data_blob_talloc(mem_ctx,
3454 cli->auth->a_u.schannel_auth->sess_key, 16);
3455 break;
3456 case PIPE_AUTH_TYPE_NTLMSSP:
3457 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3458 *session_key = data_blob_talloc(mem_ctx,
3459 cli->auth->a_u.ntlmssp_state->session_key.data,
3460 cli->auth->a_u.ntlmssp_state->session_key.length);
3461 break;
3462 case PIPE_AUTH_TYPE_KRB5:
3463 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3464 *session_key = data_blob_talloc(mem_ctx,
3465 cli->auth->a_u.kerberos_auth->session_key.data,
3466 cli->auth->a_u.kerberos_auth->session_key.length);
3467 break;
3468 case PIPE_AUTH_TYPE_NONE:
3469 default:
3470 return NT_STATUS_NO_USER_SESSION_KEY;
3473 return NT_STATUS_OK;