s3-kerberos: only use krb5 headers where required.
[Samba.git] / source / rpc_client / cli_pipe.c
blobb97656074927acdb036f61e8b984fbe2b86898f9
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
22 #include "smb_krb5.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_RPC_CLI
27 /*******************************************************************
28 interface/version dce/rpc pipe identification
29 ********************************************************************/
31 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
32 #define PIPE_SAMR "\\PIPE\\samr"
33 #define PIPE_WINREG "\\PIPE\\winreg"
34 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
35 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
36 #define PIPE_NTLSA "\\PIPE\\ntlsa"
37 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
38 #define PIPE_LSASS "\\PIPE\\lsass"
39 #define PIPE_LSARPC "\\PIPE\\lsarpc"
40 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
41 #define PIPE_NETDFS "\\PIPE\\netdfs"
42 #define PIPE_ECHO "\\PIPE\\rpcecho"
43 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
44 #define PIPE_EPM "\\PIPE\\epmapper"
45 #define PIPE_SVCCTL "\\PIPE\\svcctl"
46 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
47 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
48 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
51 * IMPORTANT!! If you update this structure, make sure to
52 * update the index #defines in smb.h.
55 static const struct pipe_id_info {
56 /* the names appear not to matter: the syntaxes _do_ matter */
58 const char *client_pipe;
59 const RPC_IFACE *abstr_syntax; /* this one is the abstract syntax id */
60 } pipe_names [] =
62 { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
63 { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
64 { PIPE_SAMR, &ndr_table_samr.syntax_id },
65 { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
66 { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
67 { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
68 { PIPE_WINREG, &ndr_table_winreg.syntax_id },
69 { PIPE_SPOOLSS, &syntax_spoolss },
70 { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
71 { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
72 { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
73 { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
74 { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
75 { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
76 { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
77 { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
78 { NULL, NULL }
81 /****************************************************************************
82 Return the pipe name from the interface.
83 ****************************************************************************/
85 const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx,
86 struct cli_state *cli,
87 const struct ndr_syntax_id *interface)
89 int i;
90 for (i = 0; pipe_names[i].client_pipe; i++) {
91 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
92 interface)) {
93 return &pipe_names[i].client_pipe[5];
98 * Here we should ask \\epmapper, but for now our code is only
99 * interested in the known pipes mentioned in pipe_names[]
102 return NULL;
105 /********************************************************************
106 Map internal value to wire value.
107 ********************************************************************/
109 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
111 switch (auth_type) {
113 case PIPE_AUTH_TYPE_NONE:
114 return RPC_ANONYMOUS_AUTH_TYPE;
116 case PIPE_AUTH_TYPE_NTLMSSP:
117 return RPC_NTLMSSP_AUTH_TYPE;
119 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
120 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
121 return RPC_SPNEGO_AUTH_TYPE;
123 case PIPE_AUTH_TYPE_SCHANNEL:
124 return RPC_SCHANNEL_AUTH_TYPE;
126 case PIPE_AUTH_TYPE_KRB5:
127 return RPC_KRB5_AUTH_TYPE;
129 default:
130 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
131 "auth type %u\n",
132 (unsigned int)auth_type ));
133 break;
135 return -1;
138 /********************************************************************
139 Pipe description for a DEBUG
140 ********************************************************************/
141 static char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli)
143 char *result;
145 switch (cli->transport_type) {
146 case NCACN_NP:
147 result = talloc_asprintf(mem_ctx, "host %s, pipe %s, "
148 "fnum 0x%x",
149 cli->desthost,
150 cli->trans.np.pipe_name,
151 (unsigned int)(cli->trans.np.fnum));
152 break;
153 case NCACN_IP_TCP:
154 case NCACN_UNIX_STREAM:
155 result = talloc_asprintf(mem_ctx, "host %s, fd %d",
156 cli->desthost, cli->trans.sock.fd);
157 break;
158 default:
159 result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
160 break;
162 SMB_ASSERT(result != NULL);
163 return result;
166 /********************************************************************
167 Rpc pipe call id.
168 ********************************************************************/
170 static uint32 get_rpc_call_id(void)
172 static uint32 call_id = 0;
173 return ++call_id;
176 /*******************************************************************
177 Read from a RPC named pipe
178 ********************************************************************/
179 static NTSTATUS rpc_read_np(struct cli_state *cli, const char *pipe_name,
180 int fnum, char *buf, off_t offset, size_t size,
181 ssize_t *pnum_read)
183 ssize_t num_read;
185 num_read = cli_read(cli, fnum, buf, offset, size);
187 DEBUG(5,("rpc_read_np: num_read = %d, read offset: %u, to read: %u\n",
188 (int)num_read, (unsigned int)offset, (unsigned int)size));
191 * A dos error of ERRDOS/ERRmoredata is not an error.
193 if (cli_is_dos_error(cli)) {
194 uint32 ecode;
195 uint8 eclass;
196 cli_dos_error(cli, &eclass, &ecode);
197 if (eclass != ERRDOS && ecode != ERRmoredata) {
198 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read "
199 "on fnum 0x%x\n", eclass, (unsigned int)ecode,
200 cli_errstr(cli), fnum));
201 return dos_to_ntstatus(eclass, ecode);
206 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
208 if (cli_is_nt_error(cli)) {
209 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
210 NT_STATUS_BUFFER_TOO_SMALL)) {
211 DEBUG(0,("rpc_read: Error (%s) in cli_read on fnum "
212 "0x%x\n", nt_errstr(cli_nt_error(cli)), fnum));
213 return cli_nt_error(cli);
217 if (num_read == -1) {
218 DEBUG(0,("rpc_read: Error - cli_read on fnum 0x%x returned "
219 "-1\n", fnum));
220 return cli_get_nt_error(cli);
223 *pnum_read = num_read;
224 return NT_STATUS_OK;
228 /*******************************************************************
229 Use SMBreadX to get rest of one fragment's worth of rpc data.
230 Will expand the current_pdu struct to the correct size.
231 ********************************************************************/
233 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
234 prs_struct *current_pdu,
235 uint32 data_to_read,
236 uint32 *current_pdu_offset)
238 size_t size = (size_t)cli->max_recv_frag;
239 uint32 stream_offset = 0;
240 ssize_t num_read = 0;
241 char *pdata;
242 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
244 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
245 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
248 * Grow the buffer if needed to accommodate the data to be read.
251 if (extra_data_size > 0) {
252 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
253 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
254 return NT_STATUS_NO_MEMORY;
256 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
259 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
261 do {
262 NTSTATUS status;
264 /* read data using SMBreadX */
265 if (size > (size_t)data_to_read) {
266 size = (size_t)data_to_read;
269 switch (cli->transport_type) {
270 case NCACN_NP:
271 status = rpc_read_np(cli->trans.np.cli,
272 cli->trans.np.pipe_name,
273 cli->trans.np.fnum, pdata,
274 (off_t)stream_offset, size,
275 &num_read);
276 break;
277 case NCACN_IP_TCP:
278 case NCACN_UNIX_STREAM:
279 status = NT_STATUS_OK;
280 num_read = sys_read(cli->trans.sock.fd, pdata, size);
281 if (num_read == -1) {
282 status = map_nt_error_from_unix(errno);
284 if (num_read == 0) {
285 status = NT_STATUS_END_OF_FILE;
287 break;
288 default:
289 DEBUG(0, ("unknown transport type %d\n",
290 cli->transport_type));
291 return NT_STATUS_INTERNAL_ERROR;
294 data_to_read -= num_read;
295 stream_offset += num_read;
296 pdata += num_read;
298 } while (num_read > 0 && data_to_read > 0);
299 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
302 * Update the current offset into current_pdu by the amount read.
304 *current_pdu_offset += stream_offset;
305 return NT_STATUS_OK;
308 /****************************************************************************
309 Try and get a PDU's worth of data from current_pdu. If not, then read more
310 from the wire.
311 ****************************************************************************/
313 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
315 NTSTATUS ret = NT_STATUS_OK;
316 uint32 current_pdu_len = prs_data_size(current_pdu);
318 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
319 if (current_pdu_len < RPC_HEADER_LEN) {
320 /* rpc_read expands the current_pdu struct as neccessary. */
321 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
322 if (!NT_STATUS_IS_OK(ret)) {
323 return ret;
327 /* This next call sets the endian bit correctly in current_pdu. */
328 /* We will propagate this to rbuf later. */
329 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
330 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
331 return NT_STATUS_BUFFER_TOO_SMALL;
334 /* Ensure we have frag_len bytes of data. */
335 if (current_pdu_len < prhdr->frag_len) {
336 /* rpc_read expands the current_pdu struct as neccessary. */
337 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
338 if (!NT_STATUS_IS_OK(ret)) {
339 return ret;
343 if (current_pdu_len < prhdr->frag_len) {
344 return NT_STATUS_BUFFER_TOO_SMALL;
347 return NT_STATUS_OK;
350 /****************************************************************************
351 NTLMSSP specific sign/seal.
352 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
353 In fact I should probably abstract these into identical pieces of code... JRA.
354 ****************************************************************************/
356 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
357 prs_struct *current_pdu,
358 uint8 *p_ss_padding_len)
360 RPC_HDR_AUTH auth_info;
361 uint32 save_offset = prs_offset(current_pdu);
362 uint32 auth_len = prhdr->auth_len;
363 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
364 unsigned char *data = NULL;
365 size_t data_len;
366 unsigned char *full_packet_data = NULL;
367 size_t full_packet_data_len;
368 DATA_BLOB auth_blob;
369 NTSTATUS status;
371 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
372 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
373 return NT_STATUS_OK;
376 if (!ntlmssp_state) {
377 return NT_STATUS_INVALID_PARAMETER;
380 /* Ensure there's enough data for an authenticated response. */
381 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
382 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
383 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
384 (unsigned int)auth_len ));
385 return NT_STATUS_BUFFER_TOO_SMALL;
389 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
390 * after the RPC header.
391 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
392 * functions as NTLMv2 checks the rpc headers also.
395 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
396 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
398 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
399 full_packet_data_len = prhdr->frag_len - auth_len;
401 /* Pull the auth header and the following data into a blob. */
402 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
403 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
404 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
405 return NT_STATUS_BUFFER_TOO_SMALL;
408 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
409 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
410 return NT_STATUS_BUFFER_TOO_SMALL;
413 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
414 auth_blob.length = auth_len;
416 switch (cli->auth->auth_level) {
417 case PIPE_AUTH_LEVEL_PRIVACY:
418 /* Data is encrypted. */
419 status = ntlmssp_unseal_packet(ntlmssp_state,
420 data, data_len,
421 full_packet_data,
422 full_packet_data_len,
423 &auth_blob);
424 if (!NT_STATUS_IS_OK(status)) {
425 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
426 "packet from %s. Error was %s.\n",
427 rpccli_pipe_txt(debug_ctx(), cli),
428 nt_errstr(status) ));
429 return status;
431 break;
432 case PIPE_AUTH_LEVEL_INTEGRITY:
433 /* Data is signed. */
434 status = ntlmssp_check_packet(ntlmssp_state,
435 data, data_len,
436 full_packet_data,
437 full_packet_data_len,
438 &auth_blob);
439 if (!NT_STATUS_IS_OK(status)) {
440 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
441 "packet from %s. Error was %s.\n",
442 rpccli_pipe_txt(debug_ctx(), cli),
443 nt_errstr(status) ));
444 return status;
446 break;
447 default:
448 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
449 "auth level %d\n", cli->auth->auth_level));
450 return NT_STATUS_INVALID_INFO_CLASS;
454 * Return the current pointer to the data offset.
457 if(!prs_set_offset(current_pdu, save_offset)) {
458 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
459 (unsigned int)save_offset ));
460 return NT_STATUS_BUFFER_TOO_SMALL;
464 * Remember the padding length. We must remove it from the real data
465 * stream once the sign/seal is done.
468 *p_ss_padding_len = auth_info.auth_pad_len;
470 return NT_STATUS_OK;
473 /****************************************************************************
474 schannel specific sign/seal.
475 ****************************************************************************/
477 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
478 prs_struct *current_pdu,
479 uint8 *p_ss_padding_len)
481 RPC_HDR_AUTH auth_info;
482 RPC_AUTH_SCHANNEL_CHK schannel_chk;
483 uint32 auth_len = prhdr->auth_len;
484 uint32 save_offset = prs_offset(current_pdu);
485 struct schannel_auth_struct *schannel_auth =
486 cli->auth->a_u.schannel_auth;
487 uint32 data_len;
489 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
490 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
491 return NT_STATUS_OK;
494 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
495 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
496 return NT_STATUS_INVALID_PARAMETER;
499 if (!schannel_auth) {
500 return NT_STATUS_INVALID_PARAMETER;
503 /* Ensure there's enough data for an authenticated response. */
504 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
505 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
506 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
507 (unsigned int)auth_len ));
508 return NT_STATUS_INVALID_PARAMETER;
511 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
513 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
514 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
515 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
516 return NT_STATUS_BUFFER_TOO_SMALL;
519 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
520 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
521 return NT_STATUS_BUFFER_TOO_SMALL;
524 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
525 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
526 auth_info.auth_type));
527 return NT_STATUS_BUFFER_TOO_SMALL;
530 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
531 &schannel_chk, current_pdu, 0)) {
532 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
533 return NT_STATUS_BUFFER_TOO_SMALL;
536 if (!schannel_decode(schannel_auth,
537 cli->auth->auth_level,
538 SENDER_IS_ACCEPTOR,
539 &schannel_chk,
540 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
541 data_len)) {
542 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
543 "Connection to %s.\n",
544 rpccli_pipe_txt(debug_ctx(), cli)));
545 return NT_STATUS_INVALID_PARAMETER;
548 /* The sequence number gets incremented on both send and receive. */
549 schannel_auth->seq_num++;
552 * Return the current pointer to the data offset.
555 if(!prs_set_offset(current_pdu, save_offset)) {
556 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
557 (unsigned int)save_offset ));
558 return NT_STATUS_BUFFER_TOO_SMALL;
562 * Remember the padding length. We must remove it from the real data
563 * stream once the sign/seal is done.
566 *p_ss_padding_len = auth_info.auth_pad_len;
568 return NT_STATUS_OK;
571 /****************************************************************************
572 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
573 ****************************************************************************/
575 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
576 prs_struct *current_pdu,
577 uint8 *p_ss_padding_len)
579 NTSTATUS ret = NT_STATUS_OK;
581 /* Paranioa checks for auth_len. */
582 if (prhdr->auth_len) {
583 if (prhdr->auth_len > prhdr->frag_len) {
584 return NT_STATUS_INVALID_PARAMETER;
587 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
588 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
589 /* Integer wrap attempt. */
590 return NT_STATUS_INVALID_PARAMETER;
595 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
598 switch(cli->auth->auth_type) {
599 case PIPE_AUTH_TYPE_NONE:
600 if (prhdr->auth_len) {
601 DEBUG(3, ("cli_pipe_validate_rpc_response: "
602 "Connection to %s - got non-zero "
603 "auth len %u.\n",
604 rpccli_pipe_txt(debug_ctx(), cli),
605 (unsigned int)prhdr->auth_len ));
606 return NT_STATUS_INVALID_PARAMETER;
608 break;
610 case PIPE_AUTH_TYPE_NTLMSSP:
611 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
612 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
613 if (!NT_STATUS_IS_OK(ret)) {
614 return ret;
616 break;
618 case PIPE_AUTH_TYPE_SCHANNEL:
619 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
620 if (!NT_STATUS_IS_OK(ret)) {
621 return ret;
623 break;
625 case PIPE_AUTH_TYPE_KRB5:
626 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
627 default:
628 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
629 "to %s - unknown internal auth type %u.\n",
630 rpccli_pipe_txt(debug_ctx(), cli),
631 cli->auth->auth_type ));
632 return NT_STATUS_INVALID_INFO_CLASS;
635 return NT_STATUS_OK;
638 /****************************************************************************
639 Do basic authentication checks on an incoming pdu.
640 ****************************************************************************/
642 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
643 prs_struct *current_pdu,
644 uint8 expected_pkt_type,
645 char **ppdata,
646 uint32 *pdata_len,
647 prs_struct *return_data)
650 NTSTATUS ret = NT_STATUS_OK;
651 uint32 current_pdu_len = prs_data_size(current_pdu);
653 if (current_pdu_len != prhdr->frag_len) {
654 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
655 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
656 return NT_STATUS_INVALID_PARAMETER;
660 * Point the return values at the real data including the RPC
661 * header. Just in case the caller wants it.
663 *ppdata = prs_data_p(current_pdu);
664 *pdata_len = current_pdu_len;
666 /* Ensure we have the correct type. */
667 switch (prhdr->pkt_type) {
668 case RPC_ALTCONTRESP:
669 case RPC_BINDACK:
671 /* Alter context and bind ack share the same packet definitions. */
672 break;
675 case RPC_RESPONSE:
677 RPC_HDR_RESP rhdr_resp;
678 uint8 ss_padding_len = 0;
680 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
681 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
682 return NT_STATUS_BUFFER_TOO_SMALL;
685 /* Here's where we deal with incoming sign/seal. */
686 ret = cli_pipe_validate_rpc_response(cli, prhdr,
687 current_pdu, &ss_padding_len);
688 if (!NT_STATUS_IS_OK(ret)) {
689 return ret;
692 /* Point the return values at the NDR data. Remember to remove any ss padding. */
693 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
695 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
696 return NT_STATUS_BUFFER_TOO_SMALL;
699 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
701 /* Remember to remove the auth footer. */
702 if (prhdr->auth_len) {
703 /* We've already done integer wrap tests on auth_len in
704 cli_pipe_validate_rpc_response(). */
705 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
706 return NT_STATUS_BUFFER_TOO_SMALL;
708 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
711 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
712 current_pdu_len, *pdata_len, ss_padding_len ));
715 * If this is the first reply, and the allocation hint is reasonably, try and
716 * set up the return_data parse_struct to the correct size.
719 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
720 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
721 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
722 "too large to allocate\n",
723 (unsigned int)rhdr_resp.alloc_hint ));
724 return NT_STATUS_NO_MEMORY;
728 break;
731 case RPC_BINDNACK:
732 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
733 "received from %s!\n",
734 rpccli_pipe_txt(debug_ctx(), cli)));
735 /* Use this for now... */
736 return NT_STATUS_NETWORK_ACCESS_DENIED;
738 case RPC_FAULT:
740 RPC_HDR_RESP rhdr_resp;
741 RPC_HDR_FAULT fault_resp;
743 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
744 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
745 return NT_STATUS_BUFFER_TOO_SMALL;
748 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
749 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
750 return NT_STATUS_BUFFER_TOO_SMALL;
753 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
754 "code %s received from %s!\n",
755 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
756 rpccli_pipe_txt(debug_ctx(), cli)));
757 if (NT_STATUS_IS_OK(fault_resp.status)) {
758 return NT_STATUS_UNSUCCESSFUL;
759 } else {
760 return fault_resp.status;
764 default:
765 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
766 "from %s!\n",
767 (unsigned int)prhdr->pkt_type,
768 rpccli_pipe_txt(debug_ctx(), cli)));
769 return NT_STATUS_INVALID_INFO_CLASS;
772 if (prhdr->pkt_type != expected_pkt_type) {
773 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
774 "got an unexpected RPC packet type - %u, not %u\n",
775 rpccli_pipe_txt(debug_ctx(), cli),
776 prhdr->pkt_type,
777 expected_pkt_type));
778 return NT_STATUS_INVALID_INFO_CLASS;
781 /* Do this just before return - we don't want to modify any rpc header
782 data before now as we may have needed to do cryptographic actions on
783 it before. */
785 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
786 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
787 "setting fragment first/last ON.\n"));
788 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
791 return NT_STATUS_OK;
794 /****************************************************************************
795 Ensure we eat the just processed pdu from the current_pdu prs_struct.
796 Normally the frag_len and buffer size will match, but on the first trans
797 reply there is a theoretical chance that buffer size > frag_len, so we must
798 deal with that.
799 ****************************************************************************/
801 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
803 uint32 current_pdu_len = prs_data_size(current_pdu);
805 if (current_pdu_len < prhdr->frag_len) {
806 return NT_STATUS_BUFFER_TOO_SMALL;
809 /* Common case. */
810 if (current_pdu_len == (uint32)prhdr->frag_len) {
811 prs_mem_free(current_pdu);
812 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
813 /* Make current_pdu dynamic with no memory. */
814 prs_give_memory(current_pdu, 0, 0, True);
815 return NT_STATUS_OK;
819 * Oh no ! More data in buffer than we processed in current pdu.
820 * Cheat. Move the data down and shrink the buffer.
823 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
824 current_pdu_len - prhdr->frag_len);
826 /* Remember to set the read offset back to zero. */
827 prs_set_offset(current_pdu, 0);
829 /* Shrink the buffer. */
830 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
831 return NT_STATUS_BUFFER_TOO_SMALL;
834 return NT_STATUS_OK;
837 /****************************************************************************
838 Send data on an rpc pipe via trans. The prs_struct data must be the last
839 pdu fragment of an NDR data stream.
841 Receive response data from an rpc pipe, which may be large...
843 Read the first fragment: unfortunately have to use SMBtrans for the first
844 bit, then SMBreadX for subsequent bits.
846 If first fragment received also wasn't the last fragment, continue
847 getting fragments until we _do_ receive the last fragment.
849 Request/Response PDU's look like the following...
851 |<------------------PDU len----------------------------------------------->|
852 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
854 +------------+-----------------+-------------+---------------+-------------+
855 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
856 +------------+-----------------+-------------+---------------+-------------+
858 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
859 signing & sealing being negotiated.
861 ****************************************************************************/
863 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
864 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
865 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
866 uint8 expected_pkt_type)
868 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
869 char *rparam = NULL;
870 uint32 rparam_len = 0;
871 char *pdata = prs_data_p(data);
872 uint32 data_len = prs_offset(data);
873 char *prdata = NULL;
874 uint32 rdata_len = 0;
875 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
876 uint32 current_rbuf_offset = 0;
877 prs_struct current_pdu;
879 #ifdef DEVELOPER
880 /* Ensure we're not sending too much. */
881 SMB_ASSERT(data_len <= max_data);
882 #endif
884 /* Set up the current pdu parse struct. */
885 prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
887 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
889 switch (cli->transport_type) {
890 case NCACN_NP: {
891 uint16 setup[2];
892 /* Create setup parameters - must be in native byte order. */
893 setup[0] = TRANSACT_DCERPCCMD;
894 setup[1] = cli->trans.np.fnum; /* Pipe file handle. */
897 * Send the last (or only) fragment of an RPC request. For
898 * small amounts of data (about 1024 bytes or so) the RPC
899 * request and response appears in a SMBtrans request and
900 * response.
903 if (!cli_api_pipe(cli->trans.np.cli, "\\PIPE\\",
904 setup, 2, 0, /* Setup, length, max */
905 NULL, 0, 0, /* Params, length, max */
906 pdata, data_len, max_data, /* data, length,
907 * max */
908 &rparam, &rparam_len, /* return params,
909 * len */
910 &prdata, &rdata_len)) /* return data, len */
912 DEBUG(0, ("rpc_api_pipe: %s returned critical error. "
913 "Error was %s\n",
914 rpccli_pipe_txt(debug_ctx(), cli),
915 cli_errstr(cli->trans.np.cli)));
916 ret = cli_get_nt_error(cli->trans.np.cli);
917 SAFE_FREE(rparam);
918 SAFE_FREE(prdata);
919 goto err;
921 break;
923 case NCACN_IP_TCP:
924 case NCACN_UNIX_STREAM:
926 ssize_t nwritten, nread;
927 nwritten = write_data(cli->trans.sock.fd, pdata, data_len);
928 if (nwritten == -1) {
929 ret = map_nt_error_from_unix(errno);
930 DEBUG(0, ("rpc_api_pipe: write_data returned %s\n",
931 strerror(errno)));
932 goto err;
934 rparam = NULL;
935 prdata = SMB_MALLOC_ARRAY(char, 1);
936 if (prdata == NULL) {
937 return NT_STATUS_NO_MEMORY;
939 nread = sys_read(cli->trans.sock.fd, prdata, 1);
940 if (nread == 0) {
941 SAFE_FREE(prdata);
943 if (nread == -1) {
944 ret = NT_STATUS_END_OF_FILE;
945 goto err;
947 rdata_len = nread;
948 break;
950 default:
951 DEBUG(0, ("unknown transport type %d\n",
952 cli->transport_type));
953 return NT_STATUS_INTERNAL_ERROR;
956 /* Throw away returned params - we know we won't use them. */
958 SAFE_FREE(rparam);
960 if (prdata == NULL) {
961 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
962 rpccli_pipe_txt(debug_ctx(), cli)));
963 /* Yes - some calls can truely return no data... */
964 prs_mem_free(&current_pdu);
965 return NT_STATUS_OK;
969 * Give this memory as dynamic to the current pdu.
972 prs_give_memory(&current_pdu, prdata, rdata_len, True);
974 /* Ensure we can mess with the return prs_struct. */
975 SMB_ASSERT(UNMARSHALLING(rbuf));
976 SMB_ASSERT(prs_data_size(rbuf) == 0);
978 /* Make rbuf dynamic with no memory. */
979 prs_give_memory(rbuf, 0, 0, True);
981 while(1) {
982 RPC_HDR rhdr;
983 char *ret_data = NULL;
984 uint32 ret_data_len = 0;
986 /* Ensure we have enough data for a pdu. */
987 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
988 if (!NT_STATUS_IS_OK(ret)) {
989 goto err;
992 /* We pass in rbuf here so if the alloc hint is set correctly
993 we can set the output size and avoid reallocs. */
995 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
996 &ret_data, &ret_data_len, rbuf);
998 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
999 prs_data_size(&current_pdu), current_rbuf_offset ));
1001 if (!NT_STATUS_IS_OK(ret)) {
1002 goto err;
1005 if ((rhdr.flags & RPC_FLG_FIRST)) {
1006 if (rhdr.pack_type[0] == 0) {
1007 /* Set the data type correctly for big-endian data on the first packet. */
1008 DEBUG(10,("rpc_api_pipe: On %s "
1009 "PDU data format is big-endian.\n",
1010 rpccli_pipe_txt(debug_ctx(), cli)));
1012 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
1013 } else {
1014 /* Check endianness on subsequent packets. */
1015 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
1016 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
1017 rbuf->bigendian_data ? "big" : "little",
1018 current_pdu.bigendian_data ? "big" : "little" ));
1019 ret = NT_STATUS_INVALID_PARAMETER;
1020 goto err;
1025 /* Now copy the data portion out of the pdu into rbuf. */
1026 if (!prs_force_grow(rbuf, ret_data_len)) {
1027 ret = NT_STATUS_NO_MEMORY;
1028 goto err;
1030 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
1031 current_rbuf_offset += ret_data_len;
1033 /* See if we've finished with all the data in current_pdu yet ? */
1034 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
1035 if (!NT_STATUS_IS_OK(ret)) {
1036 goto err;
1039 if (rhdr.flags & RPC_FLG_LAST) {
1040 break; /* We're done. */
1044 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1045 rpccli_pipe_txt(debug_ctx(), cli),
1046 (unsigned int)prs_data_size(rbuf) ));
1048 prs_mem_free(&current_pdu);
1049 return NT_STATUS_OK;
1051 err:
1053 prs_mem_free(&current_pdu);
1054 prs_mem_free(rbuf);
1055 return ret;
1058 /*******************************************************************
1059 Creates krb5 auth bind.
1060 ********************************************************************/
1062 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1063 enum pipe_auth_level auth_level,
1064 RPC_HDR_AUTH *pauth_out,
1065 prs_struct *auth_data)
1067 #ifdef HAVE_KRB5
1068 int ret;
1069 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1070 DATA_BLOB tkt = data_blob_null;
1071 DATA_BLOB tkt_wrapped = data_blob_null;
1073 /* We may change the pad length before marshalling. */
1074 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
1076 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1077 a->service_principal ));
1079 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1081 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1082 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
1084 if (ret) {
1085 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1086 "failed with %s\n",
1087 a->service_principal,
1088 error_message(ret) ));
1090 data_blob_free(&tkt);
1091 prs_mem_free(auth_data);
1092 return NT_STATUS_INVALID_PARAMETER;
1095 /* wrap that up in a nice GSS-API wrapping */
1096 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1098 data_blob_free(&tkt);
1100 /* Auth len in the rpc header doesn't include auth_header. */
1101 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1102 data_blob_free(&tkt_wrapped);
1103 prs_mem_free(auth_data);
1104 return NT_STATUS_NO_MEMORY;
1107 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1108 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1110 data_blob_free(&tkt_wrapped);
1111 return NT_STATUS_OK;
1112 #else
1113 return NT_STATUS_INVALID_PARAMETER;
1114 #endif
1117 /*******************************************************************
1118 Creates SPNEGO NTLMSSP auth bind.
1119 ********************************************************************/
1121 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1122 enum pipe_auth_level auth_level,
1123 RPC_HDR_AUTH *pauth_out,
1124 prs_struct *auth_data)
1126 NTSTATUS nt_status;
1127 DATA_BLOB null_blob = data_blob_null;
1128 DATA_BLOB request = data_blob_null;
1129 DATA_BLOB spnego_msg = data_blob_null;
1131 /* We may change the pad length before marshalling. */
1132 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1134 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1135 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1136 null_blob,
1137 &request);
1139 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1140 data_blob_free(&request);
1141 prs_mem_free(auth_data);
1142 return nt_status;
1145 /* Wrap this in SPNEGO. */
1146 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1148 data_blob_free(&request);
1150 /* Auth len in the rpc header doesn't include auth_header. */
1151 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1152 data_blob_free(&spnego_msg);
1153 prs_mem_free(auth_data);
1154 return NT_STATUS_NO_MEMORY;
1157 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1158 dump_data(5, spnego_msg.data, spnego_msg.length);
1160 data_blob_free(&spnego_msg);
1161 return NT_STATUS_OK;
1164 /*******************************************************************
1165 Creates NTLMSSP auth bind.
1166 ********************************************************************/
1168 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1169 enum pipe_auth_level auth_level,
1170 RPC_HDR_AUTH *pauth_out,
1171 prs_struct *auth_data)
1173 NTSTATUS nt_status;
1174 DATA_BLOB null_blob = data_blob_null;
1175 DATA_BLOB request = data_blob_null;
1177 /* We may change the pad length before marshalling. */
1178 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1180 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1181 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1182 null_blob,
1183 &request);
1185 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1186 data_blob_free(&request);
1187 prs_mem_free(auth_data);
1188 return nt_status;
1191 /* Auth len in the rpc header doesn't include auth_header. */
1192 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1193 data_blob_free(&request);
1194 prs_mem_free(auth_data);
1195 return NT_STATUS_NO_MEMORY;
1198 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1199 dump_data(5, request.data, request.length);
1201 data_blob_free(&request);
1202 return NT_STATUS_OK;
1205 /*******************************************************************
1206 Creates schannel auth bind.
1207 ********************************************************************/
1209 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1210 enum pipe_auth_level auth_level,
1211 RPC_HDR_AUTH *pauth_out,
1212 prs_struct *auth_data)
1214 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1216 /* We may change the pad length before marshalling. */
1217 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1219 /* Use lp_workgroup() if domain not specified */
1221 if (!cli->auth->domain || !cli->auth->domain[0]) {
1222 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1223 if (cli->auth->domain == NULL) {
1224 return NT_STATUS_NO_MEMORY;
1228 init_rpc_auth_schannel_neg(&schannel_neg, cli->auth->domain,
1229 global_myname());
1232 * Now marshall the data into the auth parse_struct.
1235 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1236 &schannel_neg, auth_data, 0)) {
1237 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1238 prs_mem_free(auth_data);
1239 return NT_STATUS_NO_MEMORY;
1242 return NT_STATUS_OK;
1245 /*******************************************************************
1246 Creates the internals of a DCE/RPC bind request or alter context PDU.
1247 ********************************************************************/
1249 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1250 prs_struct *rpc_out,
1251 uint32 rpc_call_id,
1252 const RPC_IFACE *abstract,
1253 const RPC_IFACE *transfer,
1254 RPC_HDR_AUTH *phdr_auth,
1255 prs_struct *pauth_info)
1257 RPC_HDR hdr;
1258 RPC_HDR_RB hdr_rb;
1259 RPC_CONTEXT rpc_ctx;
1260 uint16 auth_len = prs_offset(pauth_info);
1261 uint8 ss_padding_len = 0;
1262 uint16 frag_len = 0;
1264 /* create the RPC context. */
1265 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1267 /* create the bind request RPC_HDR_RB */
1268 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1270 /* Start building the frag length. */
1271 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1273 /* Do we need to pad ? */
1274 if (auth_len) {
1275 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1276 if (data_len % 8) {
1277 ss_padding_len = 8 - (data_len % 8);
1278 phdr_auth->auth_pad_len = ss_padding_len;
1280 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1283 /* Create the request RPC_HDR */
1284 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1286 /* Marshall the RPC header */
1287 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1288 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1289 return NT_STATUS_NO_MEMORY;
1292 /* Marshall the bind request data */
1293 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1294 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1295 return NT_STATUS_NO_MEMORY;
1299 * Grow the outgoing buffer to store any auth info.
1302 if(auth_len != 0) {
1303 if (ss_padding_len) {
1304 char pad[8];
1305 memset(pad, '\0', 8);
1306 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1307 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1308 return NT_STATUS_NO_MEMORY;
1312 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1313 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1314 return NT_STATUS_NO_MEMORY;
1318 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1319 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1320 return NT_STATUS_NO_MEMORY;
1324 return NT_STATUS_OK;
1327 /*******************************************************************
1328 Creates a DCE/RPC bind request.
1329 ********************************************************************/
1331 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1332 prs_struct *rpc_out,
1333 uint32 rpc_call_id,
1334 const RPC_IFACE *abstract,
1335 const RPC_IFACE *transfer,
1336 enum pipe_auth_type auth_type,
1337 enum pipe_auth_level auth_level)
1339 RPC_HDR_AUTH hdr_auth;
1340 prs_struct auth_info;
1341 NTSTATUS ret = NT_STATUS_OK;
1343 ZERO_STRUCT(hdr_auth);
1344 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1345 return NT_STATUS_NO_MEMORY;
1347 switch (auth_type) {
1348 case PIPE_AUTH_TYPE_SCHANNEL:
1349 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1350 if (!NT_STATUS_IS_OK(ret)) {
1351 prs_mem_free(&auth_info);
1352 return ret;
1354 break;
1356 case PIPE_AUTH_TYPE_NTLMSSP:
1357 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1358 if (!NT_STATUS_IS_OK(ret)) {
1359 prs_mem_free(&auth_info);
1360 return ret;
1362 break;
1364 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1365 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1366 if (!NT_STATUS_IS_OK(ret)) {
1367 prs_mem_free(&auth_info);
1368 return ret;
1370 break;
1372 case PIPE_AUTH_TYPE_KRB5:
1373 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1374 if (!NT_STATUS_IS_OK(ret)) {
1375 prs_mem_free(&auth_info);
1376 return ret;
1378 break;
1380 case PIPE_AUTH_TYPE_NONE:
1381 break;
1383 default:
1384 /* "Can't" happen. */
1385 return NT_STATUS_INVALID_INFO_CLASS;
1388 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1389 rpc_out,
1390 rpc_call_id,
1391 abstract,
1392 transfer,
1393 &hdr_auth,
1394 &auth_info);
1396 prs_mem_free(&auth_info);
1397 return ret;
1400 /*******************************************************************
1401 Create and add the NTLMSSP sign/seal auth header and data.
1402 ********************************************************************/
1404 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1405 RPC_HDR *phdr,
1406 uint32 ss_padding_len,
1407 prs_struct *outgoing_pdu)
1409 RPC_HDR_AUTH auth_info;
1410 NTSTATUS status;
1411 DATA_BLOB auth_blob = data_blob_null;
1412 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1414 if (!cli->auth->a_u.ntlmssp_state) {
1415 return NT_STATUS_INVALID_PARAMETER;
1418 /* Init and marshall the auth header. */
1419 init_rpc_hdr_auth(&auth_info,
1420 map_pipe_auth_type_to_rpc_auth_type(
1421 cli->auth->auth_type),
1422 cli->auth->auth_level,
1423 ss_padding_len,
1424 1 /* context id. */);
1426 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1427 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1428 data_blob_free(&auth_blob);
1429 return NT_STATUS_NO_MEMORY;
1432 switch (cli->auth->auth_level) {
1433 case PIPE_AUTH_LEVEL_PRIVACY:
1434 /* Data portion is encrypted. */
1435 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1436 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1437 data_and_pad_len,
1438 (unsigned char *)prs_data_p(outgoing_pdu),
1439 (size_t)prs_offset(outgoing_pdu),
1440 &auth_blob);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 data_blob_free(&auth_blob);
1443 return status;
1445 break;
1447 case PIPE_AUTH_LEVEL_INTEGRITY:
1448 /* Data is signed. */
1449 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1450 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1451 data_and_pad_len,
1452 (unsigned char *)prs_data_p(outgoing_pdu),
1453 (size_t)prs_offset(outgoing_pdu),
1454 &auth_blob);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 data_blob_free(&auth_blob);
1457 return status;
1459 break;
1461 default:
1462 /* Can't happen. */
1463 smb_panic("bad auth level");
1464 /* Notreached. */
1465 return NT_STATUS_INVALID_PARAMETER;
1468 /* Finally marshall the blob. */
1470 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1471 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1472 (unsigned int)NTLMSSP_SIG_SIZE));
1473 data_blob_free(&auth_blob);
1474 return NT_STATUS_NO_MEMORY;
1477 data_blob_free(&auth_blob);
1478 return NT_STATUS_OK;
1481 /*******************************************************************
1482 Create and add the schannel sign/seal auth header and data.
1483 ********************************************************************/
1485 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1486 RPC_HDR *phdr,
1487 uint32 ss_padding_len,
1488 prs_struct *outgoing_pdu)
1490 RPC_HDR_AUTH auth_info;
1491 RPC_AUTH_SCHANNEL_CHK verf;
1492 struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
1493 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1494 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1496 if (!sas) {
1497 return NT_STATUS_INVALID_PARAMETER;
1500 /* Init and marshall the auth header. */
1501 init_rpc_hdr_auth(&auth_info,
1502 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1503 cli->auth->auth_level,
1504 ss_padding_len,
1505 1 /* context id. */);
1507 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1508 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1509 return NT_STATUS_NO_MEMORY;
1512 switch (cli->auth->auth_level) {
1513 case PIPE_AUTH_LEVEL_PRIVACY:
1514 case PIPE_AUTH_LEVEL_INTEGRITY:
1515 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1516 sas->seq_num));
1518 schannel_encode(sas,
1519 cli->auth->auth_level,
1520 SENDER_IS_INITIATOR,
1521 &verf,
1522 data_p,
1523 data_and_pad_len);
1525 sas->seq_num++;
1526 break;
1528 default:
1529 /* Can't happen. */
1530 smb_panic("bad auth level");
1531 /* Notreached. */
1532 return NT_STATUS_INVALID_PARAMETER;
1535 /* Finally marshall the blob. */
1536 smb_io_rpc_auth_schannel_chk("",
1537 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1538 &verf,
1539 outgoing_pdu,
1542 return NT_STATUS_OK;
1545 /*******************************************************************
1546 Calculate how much data we're going to send in this packet, also
1547 work out any sign/seal padding length.
1548 ********************************************************************/
1550 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1551 uint32 data_left,
1552 uint16 *p_frag_len,
1553 uint16 *p_auth_len,
1554 uint32 *p_ss_padding)
1556 uint32 data_space, data_len;
1558 switch (cli->auth->auth_level) {
1559 case PIPE_AUTH_LEVEL_NONE:
1560 case PIPE_AUTH_LEVEL_CONNECT:
1561 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1562 data_len = MIN(data_space, data_left);
1563 *p_ss_padding = 0;
1564 *p_auth_len = 0;
1565 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1566 return data_len;
1568 case PIPE_AUTH_LEVEL_INTEGRITY:
1569 case PIPE_AUTH_LEVEL_PRIVACY:
1570 /* Treat the same for all authenticated rpc requests. */
1571 switch(cli->auth->auth_type) {
1572 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1573 case PIPE_AUTH_TYPE_NTLMSSP:
1574 *p_auth_len = NTLMSSP_SIG_SIZE;
1575 break;
1576 case PIPE_AUTH_TYPE_SCHANNEL:
1577 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1578 break;
1579 default:
1580 smb_panic("bad auth type");
1581 break;
1584 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1585 RPC_HDR_AUTH_LEN - *p_auth_len;
1587 data_len = MIN(data_space, data_left);
1588 if (data_len % 8) {
1589 *p_ss_padding = 8 - (data_len % 8);
1591 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1592 data_len + *p_ss_padding + /* data plus padding. */
1593 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1594 return data_len;
1596 default:
1597 smb_panic("bad auth level");
1598 /* Notreached. */
1599 return 0;
1603 /*******************************************************************
1604 External interface.
1605 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1606 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1607 and deals with signing/sealing details.
1608 ********************************************************************/
1610 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1611 uint8 op_num,
1612 prs_struct *in_data,
1613 prs_struct *out_data)
1615 NTSTATUS ret;
1616 uint32 data_left = prs_offset(in_data);
1617 uint32 alloc_hint = prs_offset(in_data);
1618 uint32 data_sent_thistime = 0;
1619 uint32 current_data_offset = 0;
1620 uint32 call_id = get_rpc_call_id();
1621 char pad[8];
1622 prs_struct outgoing_pdu;
1624 memset(pad, '\0', 8);
1626 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1627 /* Server is screwed up ! */
1628 return NT_STATUS_INVALID_PARAMETER;
1631 if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1632 return NT_STATUS_NO_MEMORY;
1634 while (1) {
1635 RPC_HDR hdr;
1636 RPC_HDR_REQ hdr_req;
1637 uint16 auth_len = 0;
1638 uint16 frag_len = 0;
1639 uint8 flags = 0;
1640 uint32 ss_padding = 0;
1642 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1643 &frag_len, &auth_len, &ss_padding);
1645 if (current_data_offset == 0) {
1646 flags = RPC_FLG_FIRST;
1649 if (data_sent_thistime == data_left) {
1650 flags |= RPC_FLG_LAST;
1653 /* Create and marshall the header and request header. */
1654 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1656 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1657 prs_mem_free(&outgoing_pdu);
1658 return NT_STATUS_NO_MEMORY;
1661 /* Create the rpc request RPC_HDR_REQ */
1662 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1664 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1665 prs_mem_free(&outgoing_pdu);
1666 return NT_STATUS_NO_MEMORY;
1669 /* Copy in the data, plus any ss padding. */
1670 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1671 prs_mem_free(&outgoing_pdu);
1672 return NT_STATUS_NO_MEMORY;
1675 /* Copy the sign/seal padding data. */
1676 if (ss_padding) {
1677 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1678 prs_mem_free(&outgoing_pdu);
1679 return NT_STATUS_NO_MEMORY;
1683 /* Generate any auth sign/seal and add the auth footer. */
1684 if (auth_len) {
1685 switch (cli->auth->auth_type) {
1686 case PIPE_AUTH_TYPE_NONE:
1687 break;
1688 case PIPE_AUTH_TYPE_NTLMSSP:
1689 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1690 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1691 if (!NT_STATUS_IS_OK(ret)) {
1692 prs_mem_free(&outgoing_pdu);
1693 return ret;
1695 break;
1696 case PIPE_AUTH_TYPE_SCHANNEL:
1697 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1698 if (!NT_STATUS_IS_OK(ret)) {
1699 prs_mem_free(&outgoing_pdu);
1700 return ret;
1702 break;
1703 default:
1704 smb_panic("bad auth type");
1705 break; /* notreached */
1709 /* Actually send the packet. */
1710 if (flags & RPC_FLG_LAST) {
1711 /* Last packet - send the data, get the reply and return. */
1712 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1713 prs_mem_free(&outgoing_pdu);
1715 if ((DEBUGLEVEL >= 50)
1716 && (cli->transport_type == NCACN_NP)) {
1717 char *dump_name = NULL;
1718 /* Also capture received data */
1719 if (asprintf(&dump_name, "%s/reply_%s_%d",
1720 get_dyn_LOGFILEBASE(),
1721 cli->trans.np.pipe_name, op_num) > 0) {
1722 prs_dump(dump_name, op_num, out_data);
1723 SAFE_FREE(dump_name);
1727 return ret;
1728 } else {
1729 /* More packets to come - write and continue. */
1730 ssize_t num_written;
1732 switch (cli->transport_type) {
1733 case NCACN_NP:
1734 num_written = cli_write(cli->trans.np.cli,
1735 cli->trans.np.fnum,
1736 8, /* 8 means message mode. */
1737 prs_data_p(&outgoing_pdu),
1738 (off_t)0,
1739 (size_t)hdr.frag_len);
1741 if (num_written != hdr.frag_len) {
1742 prs_mem_free(&outgoing_pdu);
1743 return cli_get_nt_error(
1744 cli->trans.np.cli);
1746 break;
1747 case NCACN_IP_TCP:
1748 case NCACN_UNIX_STREAM:
1749 num_written = write_data(
1750 cli->trans.sock.fd,
1751 prs_data_p(&outgoing_pdu),
1752 (size_t)hdr.frag_len);
1753 if (num_written != hdr.frag_len) {
1754 NTSTATUS status;
1755 status = map_nt_error_from_unix(errno);
1756 prs_mem_free(&outgoing_pdu);
1757 return status;
1759 break;
1760 default:
1761 DEBUG(0, ("unknown transport type %d\n",
1762 cli->transport_type));
1763 return NT_STATUS_INTERNAL_ERROR;
1767 current_data_offset += data_sent_thistime;
1768 data_left -= data_sent_thistime;
1770 /* Reset the marshalling position back to zero. */
1771 if (!prs_set_offset(&outgoing_pdu, 0)) {
1772 prs_mem_free(&outgoing_pdu);
1773 return NT_STATUS_NO_MEMORY;
1777 #if 0
1778 /****************************************************************************
1779 Set the handle state.
1780 ****************************************************************************/
1782 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1783 const char *pipe_name, uint16 device_state)
1785 bool state_set = False;
1786 char param[2];
1787 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1788 char *rparam = NULL;
1789 char *rdata = NULL;
1790 uint32 rparam_len, rdata_len;
1792 if (pipe_name == NULL)
1793 return False;
1795 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1796 cli->fnum, pipe_name, device_state));
1798 /* create parameters: device state */
1799 SSVAL(param, 0, device_state);
1801 /* create setup parameters. */
1802 setup[0] = 0x0001;
1803 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1805 /* send the data on \PIPE\ */
1806 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1807 setup, 2, 0, /* setup, length, max */
1808 param, 2, 0, /* param, length, max */
1809 NULL, 0, 1024, /* data, length, max */
1810 &rparam, &rparam_len, /* return param, length */
1811 &rdata, &rdata_len)) /* return data, length */
1813 DEBUG(5, ("Set Handle state: return OK\n"));
1814 state_set = True;
1817 SAFE_FREE(rparam);
1818 SAFE_FREE(rdata);
1820 return state_set;
1822 #endif
1824 /****************************************************************************
1825 Check the rpc bind acknowledge response.
1826 ****************************************************************************/
1828 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1830 if ( hdr_ba->addr.len == 0) {
1831 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1834 /* check the transfer syntax */
1835 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1836 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1837 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1838 return False;
1841 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1842 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1843 hdr_ba->res.num_results, hdr_ba->res.reason));
1846 DEBUG(5,("check_bind_response: accepted!\n"));
1847 return True;
1850 /*******************************************************************
1851 Creates a DCE/RPC bind authentication response.
1852 This is the packet that is sent back to the server once we
1853 have received a BIND-ACK, to finish the third leg of
1854 the authentication handshake.
1855 ********************************************************************/
1857 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1858 uint32 rpc_call_id,
1859 enum pipe_auth_type auth_type,
1860 enum pipe_auth_level auth_level,
1861 DATA_BLOB *pauth_blob,
1862 prs_struct *rpc_out)
1864 RPC_HDR hdr;
1865 RPC_HDR_AUTH hdr_auth;
1866 uint32 pad = 0;
1868 /* Create the request RPC_HDR */
1869 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1870 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1871 pauth_blob->length );
1873 /* Marshall it. */
1874 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1875 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1876 return NT_STATUS_NO_MEMORY;
1880 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1881 about padding - shouldn't this pad to length 8 ? JRA.
1884 /* 4 bytes padding. */
1885 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1886 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1887 return NT_STATUS_NO_MEMORY;
1890 /* Create the request RPC_HDR_AUTHA */
1891 init_rpc_hdr_auth(&hdr_auth,
1892 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1893 auth_level, 0, 1);
1895 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1896 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1897 return NT_STATUS_NO_MEMORY;
1901 * Append the auth data to the outgoing buffer.
1904 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1905 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1906 return NT_STATUS_NO_MEMORY;
1909 return NT_STATUS_OK;
1912 /****************************************************************************
1913 Create and send the third packet in an RPC auth.
1914 ****************************************************************************/
1916 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1917 RPC_HDR *phdr,
1918 prs_struct *rbuf,
1919 uint32 rpc_call_id,
1920 enum pipe_auth_type auth_type,
1921 enum pipe_auth_level auth_level)
1923 DATA_BLOB server_response = data_blob_null;
1924 DATA_BLOB client_reply = data_blob_null;
1925 RPC_HDR_AUTH hdr_auth;
1926 NTSTATUS nt_status;
1927 prs_struct rpc_out;
1928 ssize_t ret;
1930 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1931 return NT_STATUS_INVALID_PARAMETER;
1934 /* Process the returned NTLMSSP blob first. */
1935 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1936 return NT_STATUS_INVALID_PARAMETER;
1939 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1940 return NT_STATUS_INVALID_PARAMETER;
1943 /* TODO - check auth_type/auth_level match. */
1945 server_response = data_blob(NULL, phdr->auth_len);
1946 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1948 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1949 server_response,
1950 &client_reply);
1952 if (!NT_STATUS_IS_OK(nt_status)) {
1953 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1954 data_blob_free(&server_response);
1955 return nt_status;
1958 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1960 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1961 auth_type, auth_level,
1962 &client_reply, &rpc_out);
1964 if (!NT_STATUS_IS_OK(nt_status)) {
1965 prs_mem_free(&rpc_out);
1966 data_blob_free(&client_reply);
1967 data_blob_free(&server_response);
1968 return nt_status;
1971 switch (cli->transport_type) {
1972 case NCACN_NP:
1973 /* 8 here is named pipe message mode. */
1974 ret = cli_write(cli->trans.np.cli, cli->trans.np.fnum,
1975 0x8, prs_data_p(&rpc_out), 0,
1976 (size_t)prs_offset(&rpc_out));
1977 break;
1979 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1980 nt_status = cli_get_nt_error(cli->trans.np.cli);
1982 case NCACN_IP_TCP:
1983 case NCACN_UNIX_STREAM:
1984 ret = write_data(cli->trans.sock.fd, prs_data_p(&rpc_out),
1985 (size_t)prs_offset(&rpc_out));
1986 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1987 nt_status = map_nt_error_from_unix(errno);
1989 break;
1990 default:
1991 DEBUG(0, ("unknown transport type %d\n", cli->transport_type));
1992 return NT_STATUS_INTERNAL_ERROR;
1995 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1996 DEBUG(0,("rpc_send_auth_auth3: write failed. Return was %s\n",
1997 nt_errstr(nt_status)));
1998 prs_mem_free(&rpc_out);
1999 data_blob_free(&client_reply);
2000 data_blob_free(&server_response);
2001 return nt_status;
2004 DEBUG(5,("rpc_send_auth_auth3: %s sent auth3 response ok.\n",
2005 rpccli_pipe_txt(debug_ctx(), cli)));
2007 prs_mem_free(&rpc_out);
2008 data_blob_free(&client_reply);
2009 data_blob_free(&server_response);
2010 return NT_STATUS_OK;
2013 /*******************************************************************
2014 Creates a DCE/RPC bind alter context authentication request which
2015 may contain a spnego auth blobl
2016 ********************************************************************/
2018 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2019 const RPC_IFACE *abstract,
2020 const RPC_IFACE *transfer,
2021 enum pipe_auth_level auth_level,
2022 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2023 prs_struct *rpc_out)
2025 RPC_HDR_AUTH hdr_auth;
2026 prs_struct auth_info;
2027 NTSTATUS ret = NT_STATUS_OK;
2029 ZERO_STRUCT(hdr_auth);
2030 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2031 return NT_STATUS_NO_MEMORY;
2033 /* We may change the pad length before marshalling. */
2034 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
2036 if (pauth_blob->length) {
2037 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2038 prs_mem_free(&auth_info);
2039 return NT_STATUS_NO_MEMORY;
2043 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
2044 rpc_out,
2045 rpc_call_id,
2046 abstract,
2047 transfer,
2048 &hdr_auth,
2049 &auth_info);
2050 prs_mem_free(&auth_info);
2051 return ret;
2054 /*******************************************************************
2055 Third leg of the SPNEGO bind mechanism - sends alter context PDU
2056 and gets a response.
2057 ********************************************************************/
2059 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
2060 RPC_HDR *phdr,
2061 prs_struct *rbuf,
2062 uint32 rpc_call_id,
2063 const RPC_IFACE *abstract,
2064 const RPC_IFACE *transfer,
2065 enum pipe_auth_type auth_type,
2066 enum pipe_auth_level auth_level)
2068 DATA_BLOB server_spnego_response = data_blob_null;
2069 DATA_BLOB server_ntlm_response = data_blob_null;
2070 DATA_BLOB client_reply = data_blob_null;
2071 DATA_BLOB tmp_blob = data_blob_null;
2072 RPC_HDR_AUTH hdr_auth;
2073 NTSTATUS nt_status;
2074 prs_struct rpc_out;
2076 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2077 return NT_STATUS_INVALID_PARAMETER;
2080 /* Process the returned NTLMSSP blob first. */
2081 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2082 return NT_STATUS_INVALID_PARAMETER;
2085 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2086 return NT_STATUS_INVALID_PARAMETER;
2089 server_spnego_response = data_blob(NULL, phdr->auth_len);
2090 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2092 /* The server might give us back two challenges - tmp_blob is for the second. */
2093 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
2094 data_blob_free(&server_spnego_response);
2095 data_blob_free(&server_ntlm_response);
2096 data_blob_free(&tmp_blob);
2097 return NT_STATUS_INVALID_PARAMETER;
2100 /* We're finished with the server spnego response and the tmp_blob. */
2101 data_blob_free(&server_spnego_response);
2102 data_blob_free(&tmp_blob);
2104 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
2105 server_ntlm_response,
2106 &client_reply);
2108 /* Finished with the server_ntlm response */
2109 data_blob_free(&server_ntlm_response);
2111 if (!NT_STATUS_IS_OK(nt_status)) {
2112 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
2113 data_blob_free(&client_reply);
2114 return nt_status;
2117 /* SPNEGO wrap the client reply. */
2118 tmp_blob = spnego_gen_auth(client_reply);
2119 data_blob_free(&client_reply);
2120 client_reply = tmp_blob;
2121 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
2123 /* Now prepare the alter context pdu. */
2124 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
2126 nt_status = create_rpc_alter_context(rpc_call_id,
2127 abstract,
2128 transfer,
2129 auth_level,
2130 &client_reply,
2131 &rpc_out);
2133 data_blob_free(&client_reply);
2135 if (!NT_STATUS_IS_OK(nt_status)) {
2136 prs_mem_free(&rpc_out);
2137 return nt_status;
2140 /* Initialize the returning data struct. */
2141 prs_mem_free(rbuf);
2142 prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
2144 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
2145 if (!NT_STATUS_IS_OK(nt_status)) {
2146 prs_mem_free(&rpc_out);
2147 return nt_status;
2150 prs_mem_free(&rpc_out);
2152 /* Get the auth blob from the reply. */
2153 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
2154 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
2155 return NT_STATUS_BUFFER_TOO_SMALL;
2158 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2159 return NT_STATUS_INVALID_PARAMETER;
2162 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2163 return NT_STATUS_INVALID_PARAMETER;
2166 server_spnego_response = data_blob(NULL, phdr->auth_len);
2167 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2169 /* Check we got a valid auth response. */
2170 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
2171 data_blob_free(&server_spnego_response);
2172 data_blob_free(&tmp_blob);
2173 return NT_STATUS_INVALID_PARAMETER;
2176 data_blob_free(&server_spnego_response);
2177 data_blob_free(&tmp_blob);
2179 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2180 "%s.\n", rpccli_pipe_txt(debug_ctx(), cli)));
2182 return NT_STATUS_OK;
2185 /****************************************************************************
2186 Do an rpc bind.
2187 ****************************************************************************/
2189 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2190 struct cli_pipe_auth_data *auth)
2192 RPC_HDR hdr;
2193 RPC_HDR_BA hdr_ba;
2194 prs_struct rpc_out;
2195 prs_struct rbuf;
2196 uint32 rpc_call_id;
2197 NTSTATUS status;
2199 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2200 rpccli_pipe_txt(debug_ctx(), cli),
2201 (unsigned int)auth->auth_type,
2202 (unsigned int)auth->auth_level ));
2204 cli->auth = talloc_move(cli, &auth);
2206 prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2208 rpc_call_id = get_rpc_call_id();
2210 /* Marshall the outgoing data. */
2211 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2212 &cli->abstract_syntax,
2213 &cli->transfer_syntax,
2214 cli->auth->auth_type,
2215 cli->auth->auth_level);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 prs_mem_free(&rpc_out);
2219 return status;
2222 /* Initialize the incoming data struct. */
2223 prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2225 /* send data on \PIPE\. receive a response */
2226 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2227 if (!NT_STATUS_IS_OK(status)) {
2228 prs_mem_free(&rpc_out);
2229 return status;
2232 prs_mem_free(&rpc_out);
2234 DEBUG(3,("rpc_pipe_bind: %s bind request returned ok.\n",
2235 rpccli_pipe_txt(debug_ctx(), cli)));
2237 /* Unmarshall the RPC header */
2238 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2239 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2240 prs_mem_free(&rbuf);
2241 return NT_STATUS_BUFFER_TOO_SMALL;
2244 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2245 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2246 prs_mem_free(&rbuf);
2247 return NT_STATUS_BUFFER_TOO_SMALL;
2250 if(!check_bind_response(&hdr_ba, &cli->transfer_syntax)) {
2251 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2252 prs_mem_free(&rbuf);
2253 return NT_STATUS_BUFFER_TOO_SMALL;
2256 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2257 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2259 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2260 switch(cli->auth->auth_type) {
2262 case PIPE_AUTH_TYPE_NONE:
2263 case PIPE_AUTH_TYPE_SCHANNEL:
2264 /* Bind complete. */
2265 break;
2267 case PIPE_AUTH_TYPE_NTLMSSP:
2268 /* Need to send AUTH3 packet - no reply. */
2269 status = rpc_finish_auth3_bind(
2270 cli, &hdr, &rbuf, rpc_call_id,
2271 cli->auth->auth_type,
2272 cli->auth->auth_level);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 prs_mem_free(&rbuf);
2275 return status;
2277 break;
2279 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2280 /* Need to send alter context request and reply. */
2281 status = rpc_finish_spnego_ntlmssp_bind(
2282 cli, &hdr, &rbuf, rpc_call_id,
2283 &cli->abstract_syntax, &cli->transfer_syntax,
2284 cli->auth->auth_type, cli->auth->auth_level);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 prs_mem_free(&rbuf);
2287 return status;
2289 break;
2291 case PIPE_AUTH_TYPE_KRB5:
2292 /* */
2294 default:
2295 DEBUG(0,("cli_finish_bind_auth: unknown auth type "
2296 "%u\n", (unsigned int)cli->auth->auth_type));
2297 prs_mem_free(&rbuf);
2298 return NT_STATUS_INVALID_INFO_CLASS;
2301 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2302 if (cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP
2303 || cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2304 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2305 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2306 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2307 prs_mem_free(&rbuf);
2308 return NT_STATUS_INVALID_PARAMETER;
2311 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2312 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2313 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2314 prs_mem_free(&rbuf);
2315 return NT_STATUS_INVALID_PARAMETER;
2320 prs_mem_free(&rbuf);
2321 return NT_STATUS_OK;
2323 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2324 unsigned int timeout)
2326 struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
2328 if (cli == NULL) {
2329 return 0;
2331 return cli_set_timeout(cli, timeout);
2334 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16])
2336 if ((cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2337 || (cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2338 memcpy(nt_hash, cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2339 return true;
2342 if (cli->transport_type == NCACN_NP) {
2343 E_md4hash(cli->trans.np.cli->pwd.password, nt_hash);
2344 return true;
2347 return false;
2350 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
2352 if (p == NULL) {
2353 return NULL;
2355 if (p->transport_type == NCACN_NP) {
2356 return p->trans.np.cli;
2358 return NULL;
2361 static int rpc_pipe_destructor(struct rpc_pipe_client *p)
2363 if (p->transport_type == NCACN_NP) {
2364 bool ret;
2365 ret = cli_close(p->trans.np.cli, p->trans.np.fnum);
2366 if (!ret) {
2367 DEBUG(1, ("rpc_pipe_destructor: cli_close failed on "
2368 "pipe %s. Error was %s\n",
2369 rpccli_pipe_txt(debug_ctx(), p),
2370 cli_errstr(p->trans.np.cli)));
2373 DEBUG(10, ("rpc_pipe_destructor: closed %s\n",
2374 rpccli_pipe_txt(debug_ctx(), p)));
2376 DLIST_REMOVE(p->trans.np.cli->pipe_list, p);
2377 return ret ? -1 : 0;
2380 return -1;
2383 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2384 struct cli_pipe_auth_data **presult)
2386 struct cli_pipe_auth_data *result;
2388 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2389 if (result == NULL) {
2390 return NT_STATUS_NO_MEMORY;
2393 result->auth_type = PIPE_AUTH_TYPE_NONE;
2394 result->auth_level = PIPE_AUTH_LEVEL_NONE;
2396 result->user_name = talloc_strdup(result, "");
2397 result->domain = talloc_strdup(result, "");
2398 if ((result->user_name == NULL) || (result->domain == NULL)) {
2399 TALLOC_FREE(result);
2400 return NT_STATUS_NO_MEMORY;
2403 *presult = result;
2404 return NT_STATUS_OK;
2407 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2409 ntlmssp_end(&auth->a_u.ntlmssp_state);
2410 return 0;
2413 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2414 enum pipe_auth_type auth_type,
2415 enum pipe_auth_level auth_level,
2416 const char *domain,
2417 const char *username,
2418 const char *password,
2419 struct cli_pipe_auth_data **presult)
2421 struct cli_pipe_auth_data *result;
2422 NTSTATUS status;
2424 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2425 if (result == NULL) {
2426 return NT_STATUS_NO_MEMORY;
2429 result->auth_type = auth_type;
2430 result->auth_level = auth_level;
2432 result->user_name = talloc_strdup(result, username);
2433 result->domain = talloc_strdup(result, domain);
2434 if ((result->user_name == NULL) || (result->domain == NULL)) {
2435 status = NT_STATUS_NO_MEMORY;
2436 goto fail;
2439 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
2440 if (!NT_STATUS_IS_OK(status)) {
2441 goto fail;
2444 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2446 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 goto fail;
2451 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 goto fail;
2456 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2457 if (!NT_STATUS_IS_OK(status)) {
2458 goto fail;
2462 * Turn off sign+seal to allow selected auth level to turn it back on.
2464 result->a_u.ntlmssp_state->neg_flags &=
2465 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2467 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2468 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2469 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2470 result->a_u.ntlmssp_state->neg_flags
2471 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2474 *presult = result;
2475 return NT_STATUS_OK;
2477 fail:
2478 TALLOC_FREE(result);
2479 return status;
2482 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2483 enum pipe_auth_level auth_level,
2484 const uint8_t sess_key[16],
2485 struct cli_pipe_auth_data **presult)
2487 struct cli_pipe_auth_data *result;
2489 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2490 if (result == NULL) {
2491 return NT_STATUS_NO_MEMORY;
2494 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2495 result->auth_level = auth_level;
2497 result->user_name = talloc_strdup(result, "");
2498 result->domain = talloc_strdup(result, domain);
2499 if ((result->user_name == NULL) || (result->domain == NULL)) {
2500 goto fail;
2503 result->a_u.schannel_auth = talloc(result,
2504 struct schannel_auth_struct);
2505 if (result->a_u.schannel_auth == NULL) {
2506 goto fail;
2509 memcpy(result->a_u.schannel_auth->sess_key, sess_key,
2510 sizeof(result->a_u.schannel_auth->sess_key));
2511 result->a_u.schannel_auth->seq_num = 0;
2513 *presult = result;
2514 return NT_STATUS_OK;
2516 fail:
2517 TALLOC_FREE(result);
2518 return NT_STATUS_NO_MEMORY;
2521 #ifdef HAVE_KRB5
2522 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2524 data_blob_free(&auth->session_key);
2525 return 0;
2527 #endif
2529 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2530 enum pipe_auth_level auth_level,
2531 const char *service_princ,
2532 const char *username,
2533 const char *password,
2534 struct cli_pipe_auth_data **presult)
2536 #ifdef HAVE_KRB5
2537 struct cli_pipe_auth_data *result;
2539 if ((username != NULL) && (password != NULL)) {
2540 int ret = kerberos_kinit_password(username, password, 0, NULL);
2541 if (ret != 0) {
2542 return NT_STATUS_ACCESS_DENIED;
2546 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2547 if (result == NULL) {
2548 return NT_STATUS_NO_MEMORY;
2551 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2552 result->auth_level = auth_level;
2555 * Username / domain need fixing!
2557 result->user_name = talloc_strdup(result, "");
2558 result->domain = talloc_strdup(result, "");
2559 if ((result->user_name == NULL) || (result->domain == NULL)) {
2560 goto fail;
2563 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2564 result, struct kerberos_auth_struct);
2565 if (result->a_u.kerberos_auth == NULL) {
2566 goto fail;
2568 talloc_set_destructor(result->a_u.kerberos_auth,
2569 cli_auth_kerberos_data_destructor);
2571 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2572 result, service_princ);
2573 if (result->a_u.kerberos_auth->service_principal == NULL) {
2574 goto fail;
2577 *presult = result;
2578 return NT_STATUS_OK;
2580 fail:
2581 TALLOC_FREE(result);
2582 return NT_STATUS_NO_MEMORY;
2583 #else
2584 return NT_STATUS_NOT_SUPPORTED;
2585 #endif
2588 static int rpc_pipe_sock_destructor(struct rpc_pipe_client *p)
2590 close(p->trans.sock.fd);
2591 return 0;
2595 * Create an rpc pipe client struct, connecting to a tcp port.
2597 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2598 uint16_t port,
2599 const struct ndr_syntax_id *abstract_syntax,
2600 struct rpc_pipe_client **presult)
2602 struct rpc_pipe_client *result;
2603 struct sockaddr_storage addr;
2604 NTSTATUS status;
2606 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2607 if (result == NULL) {
2608 return NT_STATUS_NO_MEMORY;
2611 result->transport_type = NCACN_IP_TCP;
2613 result->abstract_syntax = *abstract_syntax;
2614 result->transfer_syntax = ndr_transfer_syntax;
2616 result->desthost = talloc_strdup(result, host);
2617 result->srv_name_slash = talloc_asprintf_strupper_m(
2618 result, "\\\\%s", result->desthost);
2619 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2620 status = NT_STATUS_NO_MEMORY;
2621 goto fail;
2624 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2625 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2627 if (!resolve_name(host, &addr, 0)) {
2628 status = NT_STATUS_NOT_FOUND;
2629 goto fail;
2632 result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60);
2633 if (result->trans.sock.fd == -1) {
2634 status = map_nt_error_from_unix(errno);
2635 goto fail;
2638 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2640 *presult = result;
2641 return NT_STATUS_OK;
2643 fail:
2644 TALLOC_FREE(result);
2645 return status;
2649 * Determine the tcp port on which a dcerpc interface is listening
2650 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2651 * target host.
2653 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2654 const struct ndr_syntax_id *abstract_syntax,
2655 uint16_t *pport)
2657 NTSTATUS status;
2658 struct rpc_pipe_client *epm_pipe = NULL;
2659 struct cli_pipe_auth_data *auth = NULL;
2660 struct dcerpc_binding *map_binding = NULL;
2661 struct dcerpc_binding *res_binding = NULL;
2662 struct epm_twr_t *map_tower = NULL;
2663 struct epm_twr_t *res_towers = NULL;
2664 struct policy_handle *entry_handle = NULL;
2665 uint32_t num_towers = 0;
2666 uint32_t max_towers = 1;
2667 struct epm_twr_p_t towers;
2668 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2670 if (pport == NULL) {
2671 status = NT_STATUS_INVALID_PARAMETER;
2672 goto done;
2675 /* open the connection to the endpoint mapper */
2676 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2677 &ndr_table_epmapper.syntax_id,
2678 &epm_pipe);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 goto done;
2684 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2685 if (!NT_STATUS_IS_OK(status)) {
2686 goto done;
2689 status = rpc_pipe_bind(epm_pipe, auth);
2690 if (!NT_STATUS_IS_OK(status)) {
2691 goto done;
2694 /* create tower for asking the epmapper */
2696 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2697 if (map_binding == NULL) {
2698 status = NT_STATUS_NO_MEMORY;
2699 goto done;
2702 map_binding->transport = NCACN_IP_TCP;
2703 map_binding->object = *abstract_syntax;
2704 map_binding->host = host; /* needed? */
2705 map_binding->endpoint = "0"; /* correct? needed? */
2707 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2708 if (map_tower == NULL) {
2709 status = NT_STATUS_NO_MEMORY;
2710 goto done;
2713 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2714 &(map_tower->tower));
2715 if (!NT_STATUS_IS_OK(status)) {
2716 goto done;
2719 /* allocate further parameters for the epm_Map call */
2721 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2722 if (res_towers == NULL) {
2723 status = NT_STATUS_NO_MEMORY;
2724 goto done;
2726 towers.twr = res_towers;
2728 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2729 if (entry_handle == NULL) {
2730 status = NT_STATUS_NO_MEMORY;
2731 goto done;
2734 /* ask the endpoint mapper for the port */
2736 status = rpccli_epm_Map(epm_pipe,
2737 tmp_ctx,
2738 CONST_DISCARD(struct GUID *,
2739 &(abstract_syntax->uuid)),
2740 map_tower,
2741 entry_handle,
2742 max_towers,
2743 &num_towers,
2744 &towers);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 goto done;
2750 if (num_towers != 1) {
2751 status = NT_STATUS_UNSUCCESSFUL;
2752 goto done;
2755 /* extract the port from the answer */
2757 status = dcerpc_binding_from_tower(tmp_ctx,
2758 &(towers.twr->tower),
2759 &res_binding);
2760 if (!NT_STATUS_IS_OK(status)) {
2761 goto done;
2764 /* are further checks here necessary? */
2765 if (res_binding->transport != NCACN_IP_TCP) {
2766 status = NT_STATUS_UNSUCCESSFUL;
2767 goto done;
2770 *pport = (uint16_t)atoi(res_binding->endpoint);
2772 done:
2773 TALLOC_FREE(tmp_ctx);
2774 return status;
2778 * Create a rpc pipe client struct, connecting to a host via tcp.
2779 * The port is determined by asking the endpoint mapper on the given
2780 * host.
2782 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2783 const struct ndr_syntax_id *abstract_syntax,
2784 struct rpc_pipe_client **presult)
2786 NTSTATUS status;
2787 uint16_t port = 0;
2789 *presult = NULL;
2791 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 goto done;
2796 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
2797 abstract_syntax, presult);
2799 done:
2800 return status;
2803 /********************************************************************
2804 Create a rpc pipe client struct, connecting to a unix domain socket
2805 ********************************************************************/
2806 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2807 const struct ndr_syntax_id *abstract_syntax,
2808 struct rpc_pipe_client **presult)
2810 struct rpc_pipe_client *result;
2811 struct sockaddr_un addr;
2812 NTSTATUS status;
2814 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2815 if (result == NULL) {
2816 return NT_STATUS_NO_MEMORY;
2819 result->transport_type = NCACN_UNIX_STREAM;
2821 result->abstract_syntax = *abstract_syntax;
2822 result->transfer_syntax = ndr_transfer_syntax;
2824 result->desthost = get_myname(result);
2825 result->srv_name_slash = talloc_asprintf_strupper_m(
2826 result, "\\\\%s", result->desthost);
2827 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2828 status = NT_STATUS_NO_MEMORY;
2829 goto fail;
2832 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2833 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2835 result->trans.sock.fd = socket(AF_UNIX, SOCK_STREAM, 0);
2836 if (result->trans.sock.fd == -1) {
2837 status = map_nt_error_from_unix(errno);
2838 goto fail;
2841 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2843 ZERO_STRUCT(addr);
2844 addr.sun_family = AF_UNIX;
2845 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2847 if (sys_connect(result->trans.sock.fd,
2848 (struct sockaddr *)&addr) == -1) {
2849 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2850 strerror(errno)));
2851 close(result->trans.sock.fd);
2852 return map_nt_error_from_unix(errno);
2855 *presult = result;
2856 return NT_STATUS_OK;
2858 fail:
2859 TALLOC_FREE(result);
2860 return status;
2864 /****************************************************************************
2865 Open a named pipe over SMB to a remote server.
2867 * CAVEAT CALLER OF THIS FUNCTION:
2868 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2869 * so be sure that this function is called AFTER any structure (vs pointer)
2870 * assignment of the cli. In particular, libsmbclient does structure
2871 * assignments of cli, which invalidates the data in the returned
2872 * rpc_pipe_client if this function is called before the structure assignment
2873 * of cli.
2875 ****************************************************************************/
2877 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2878 const struct ndr_syntax_id *abstract_syntax,
2879 struct rpc_pipe_client **presult)
2881 struct rpc_pipe_client *result;
2882 int fnum;
2884 /* sanity check to protect against crashes */
2886 if ( !cli ) {
2887 return NT_STATUS_INVALID_HANDLE;
2890 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2891 if (result == NULL) {
2892 return NT_STATUS_NO_MEMORY;
2895 result->transport_type = NCACN_NP;
2897 result->trans.np.pipe_name = cli_get_pipe_name_from_iface(
2898 result, cli, abstract_syntax);
2899 if (result->trans.np.pipe_name == NULL) {
2900 DEBUG(1, ("Could not find pipe for interface\n"));
2901 TALLOC_FREE(result);
2902 return NT_STATUS_INVALID_PARAMETER;
2905 result->trans.np.cli = cli;
2906 result->abstract_syntax = *abstract_syntax;
2907 result->transfer_syntax = ndr_transfer_syntax;
2908 result->desthost = talloc_strdup(result, cli->desthost);
2909 result->srv_name_slash = talloc_asprintf_strupper_m(
2910 result, "\\\\%s", result->desthost);
2912 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2913 TALLOC_FREE(result);
2914 return NT_STATUS_NO_MEMORY;
2917 fnum = cli_nt_create(cli, result->trans.np.pipe_name,
2918 DESIRED_ACCESS_PIPE);
2919 if (fnum == -1) {
2920 DEBUG(3,("rpc_pipe_open_np: cli_nt_create failed on pipe %s "
2921 "to machine %s. Error was %s\n",
2922 result->trans.np.pipe_name, cli->desthost,
2923 cli_errstr(cli)));
2924 TALLOC_FREE(result);
2925 return cli_get_nt_error(cli);
2928 result->trans.np.fnum = fnum;
2930 DLIST_ADD(cli->pipe_list, result);
2931 talloc_set_destructor(result, rpc_pipe_destructor);
2933 *presult = result;
2934 return NT_STATUS_OK;
2937 /****************************************************************************
2938 Open a pipe to a remote server.
2939 ****************************************************************************/
2941 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2942 enum dcerpc_transport_t transport,
2943 const struct ndr_syntax_id *interface,
2944 struct rpc_pipe_client **presult)
2946 switch (transport) {
2947 case NCACN_IP_TCP:
2948 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2949 presult);
2950 case NCACN_NP:
2951 return rpc_pipe_open_np(cli, interface, presult);
2952 default:
2953 return NT_STATUS_NOT_IMPLEMENTED;
2957 /****************************************************************************
2958 Open a named pipe to an SMB server and bind anonymously.
2959 ****************************************************************************/
2961 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2962 enum dcerpc_transport_t transport,
2963 const struct ndr_syntax_id *interface,
2964 struct rpc_pipe_client **presult)
2966 struct rpc_pipe_client *result;
2967 struct cli_pipe_auth_data *auth;
2968 NTSTATUS status;
2970 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2971 if (!NT_STATUS_IS_OK(status)) {
2972 return status;
2975 status = rpccli_anon_bind_data(result, &auth);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2978 nt_errstr(status)));
2979 TALLOC_FREE(result);
2980 return status;
2984 * This is a bit of an abstraction violation due to the fact that an
2985 * anonymous bind on an authenticated SMB inherits the user/domain
2986 * from the enclosing SMB creds
2989 TALLOC_FREE(auth->user_name);
2990 TALLOC_FREE(auth->domain);
2992 auth->user_name = talloc_strdup(auth, cli->user_name);
2993 auth->domain = talloc_strdup(auth, cli->domain);
2995 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2996 TALLOC_FREE(result);
2997 return NT_STATUS_NO_MEMORY;
3000 status = rpc_pipe_bind(result, auth);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 int lvl = 0;
3003 if (ndr_syntax_id_equal(interface,
3004 &ndr_table_dssetup.syntax_id)) {
3005 /* non AD domains just don't have this pipe, avoid
3006 * level 0 statement in that case - gd */
3007 lvl = 3;
3009 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3010 "%s failed with error %s\n",
3011 cli_get_pipe_name_from_iface(debug_ctx(), cli,
3012 interface),
3013 nt_errstr(status) ));
3014 TALLOC_FREE(result);
3015 return status;
3018 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3019 "%s and bound anonymously.\n", result->trans.np.pipe_name,
3020 cli->desthost ));
3022 *presult = result;
3023 return NT_STATUS_OK;
3026 /****************************************************************************
3027 ****************************************************************************/
3029 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3030 const struct ndr_syntax_id *interface,
3031 struct rpc_pipe_client **presult)
3033 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3034 interface, presult);
3037 /****************************************************************************
3038 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3039 ****************************************************************************/
3041 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3042 const struct ndr_syntax_id *interface,
3043 enum dcerpc_transport_t transport,
3044 enum pipe_auth_type auth_type,
3045 enum pipe_auth_level auth_level,
3046 const char *domain,
3047 const char *username,
3048 const char *password,
3049 struct rpc_pipe_client **presult)
3051 struct rpc_pipe_client *result;
3052 struct cli_pipe_auth_data *auth;
3053 NTSTATUS status;
3055 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3056 if (!NT_STATUS_IS_OK(status)) {
3057 return status;
3060 status = rpccli_ntlmssp_bind_data(
3061 result, auth_type, auth_level, domain, username,
3062 cli->pwd.null_pwd ? NULL : password, &auth);
3063 if (!NT_STATUS_IS_OK(status)) {
3064 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3065 nt_errstr(status)));
3066 goto err;
3069 status = rpc_pipe_bind(result, auth);
3070 if (!NT_STATUS_IS_OK(status)) {
3071 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3072 nt_errstr(status) ));
3073 goto err;
3076 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3077 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3078 result->trans.np.pipe_name, cli->desthost,
3079 domain, username ));
3081 *presult = result;
3082 return NT_STATUS_OK;
3084 err:
3086 TALLOC_FREE(result);
3087 return status;
3090 /****************************************************************************
3091 External interface.
3092 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3093 ****************************************************************************/
3095 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3096 const struct ndr_syntax_id *interface,
3097 enum dcerpc_transport_t transport,
3098 enum pipe_auth_level auth_level,
3099 const char *domain,
3100 const char *username,
3101 const char *password,
3102 struct rpc_pipe_client **presult)
3104 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3105 interface,
3106 transport,
3107 PIPE_AUTH_TYPE_NTLMSSP,
3108 auth_level,
3109 domain,
3110 username,
3111 password,
3112 presult);
3115 /****************************************************************************
3116 External interface.
3117 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3118 ****************************************************************************/
3120 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3121 const struct ndr_syntax_id *interface,
3122 enum dcerpc_transport_t transport,
3123 enum pipe_auth_level auth_level,
3124 const char *domain,
3125 const char *username,
3126 const char *password,
3127 struct rpc_pipe_client **presult)
3129 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3130 interface,
3131 transport,
3132 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3133 auth_level,
3134 domain,
3135 username,
3136 password,
3137 presult);
3140 /****************************************************************************
3141 Get a the schannel session key out of an already opened netlogon pipe.
3142 ****************************************************************************/
3143 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3144 struct cli_state *cli,
3145 const char *domain,
3146 uint32 *pneg_flags)
3148 uint32 sec_chan_type = 0;
3149 unsigned char machine_pwd[16];
3150 const char *machine_account;
3151 NTSTATUS status;
3153 /* Get the machine account credentials from secrets.tdb. */
3154 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3155 &sec_chan_type))
3157 DEBUG(0, ("get_schannel_session_key: could not fetch "
3158 "trust account password for domain '%s'\n",
3159 domain));
3160 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3163 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3164 cli->desthost, /* server name */
3165 domain, /* domain */
3166 global_myname(), /* client name */
3167 machine_account, /* machine account name */
3168 machine_pwd,
3169 sec_chan_type,
3170 pneg_flags);
3172 if (!NT_STATUS_IS_OK(status)) {
3173 DEBUG(3, ("get_schannel_session_key_common: "
3174 "rpccli_netlogon_setup_creds failed with result %s "
3175 "to server %s, domain %s, machine account %s.\n",
3176 nt_errstr(status), cli->desthost, domain,
3177 machine_account ));
3178 return status;
3181 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3182 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3183 cli->desthost));
3184 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3187 return NT_STATUS_OK;;
3190 /****************************************************************************
3191 Open a netlogon pipe and get the schannel session key.
3192 Now exposed to external callers.
3193 ****************************************************************************/
3196 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3197 const char *domain,
3198 uint32 *pneg_flags,
3199 struct rpc_pipe_client **presult)
3201 struct rpc_pipe_client *netlogon_pipe = NULL;
3202 NTSTATUS status;
3204 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3205 &netlogon_pipe);
3206 if (!NT_STATUS_IS_OK(status)) {
3207 return status;
3210 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3211 pneg_flags);
3212 if (!NT_STATUS_IS_OK(status)) {
3213 TALLOC_FREE(netlogon_pipe);
3214 return status;
3217 *presult = netlogon_pipe;
3218 return NT_STATUS_OK;
3221 /****************************************************************************
3222 External interface.
3223 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3224 using session_key. sign and seal.
3225 ****************************************************************************/
3227 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3228 const struct ndr_syntax_id *interface,
3229 enum dcerpc_transport_t transport,
3230 enum pipe_auth_level auth_level,
3231 const char *domain,
3232 const struct dcinfo *pdc,
3233 struct rpc_pipe_client **presult)
3235 struct rpc_pipe_client *result;
3236 struct cli_pipe_auth_data *auth;
3237 NTSTATUS status;
3239 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 return status;
3244 status = rpccli_schannel_bind_data(result, domain, auth_level,
3245 pdc->sess_key, &auth);
3246 if (!NT_STATUS_IS_OK(status)) {
3247 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3248 nt_errstr(status)));
3249 TALLOC_FREE(result);
3250 return status;
3253 status = rpc_pipe_bind(result, auth);
3254 if (!NT_STATUS_IS_OK(status)) {
3255 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3256 "cli_rpc_pipe_bind failed with error %s\n",
3257 nt_errstr(status) ));
3258 TALLOC_FREE(result);
3259 return status;
3263 * The credentials on a new netlogon pipe are the ones we are passed
3264 * in - copy them over.
3266 result->dc = (struct dcinfo *)talloc_memdup(result, pdc, sizeof(*pdc));
3267 if (result->dc == NULL) {
3268 DEBUG(0, ("talloc failed\n"));
3269 TALLOC_FREE(result);
3270 return NT_STATUS_NO_MEMORY;
3273 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3274 "for domain %s "
3275 "and bound using schannel.\n",
3276 result->trans.np.pipe_name, cli->desthost, domain ));
3278 *presult = result;
3279 return NT_STATUS_OK;
3282 /****************************************************************************
3283 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3284 Fetch the session key ourselves using a temporary netlogon pipe. This
3285 version uses an ntlmssp auth bound netlogon pipe to get the key.
3286 ****************************************************************************/
3288 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3289 const char *domain,
3290 const char *username,
3291 const char *password,
3292 uint32 *pneg_flags,
3293 struct rpc_pipe_client **presult)
3295 struct rpc_pipe_client *netlogon_pipe = NULL;
3296 NTSTATUS status;
3298 status = cli_rpc_pipe_open_spnego_ntlmssp(
3299 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3300 PIPE_AUTH_LEVEL_PRIVACY,
3301 domain, username, password, &netlogon_pipe);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 return status;
3306 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3307 pneg_flags);
3308 if (!NT_STATUS_IS_OK(status)) {
3309 TALLOC_FREE(netlogon_pipe);
3310 return status;
3313 *presult = netlogon_pipe;
3314 return NT_STATUS_OK;
3317 /****************************************************************************
3318 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3319 Fetch the session key ourselves using a temporary netlogon pipe. This version
3320 uses an ntlmssp bind to get the session key.
3321 ****************************************************************************/
3323 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3324 const struct ndr_syntax_id *interface,
3325 enum dcerpc_transport_t transport,
3326 enum pipe_auth_level auth_level,
3327 const char *domain,
3328 const char *username,
3329 const char *password,
3330 struct rpc_pipe_client **presult)
3332 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3333 struct rpc_pipe_client *netlogon_pipe = NULL;
3334 struct rpc_pipe_client *result = NULL;
3335 NTSTATUS status;
3337 status = get_schannel_session_key_auth_ntlmssp(
3338 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3339 if (!NT_STATUS_IS_OK(status)) {
3340 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3341 "key from server %s for domain %s.\n",
3342 cli->desthost, domain ));
3343 return status;
3346 status = cli_rpc_pipe_open_schannel_with_key(
3347 cli, interface, transport, auth_level, domain, netlogon_pipe->dc,
3348 &result);
3350 /* Now we've bound using the session key we can close the netlog pipe. */
3351 TALLOC_FREE(netlogon_pipe);
3353 if (NT_STATUS_IS_OK(status)) {
3354 *presult = result;
3356 return status;
3359 /****************************************************************************
3360 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3361 Fetch the session key ourselves using a temporary netlogon pipe.
3362 ****************************************************************************/
3364 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3365 const struct ndr_syntax_id *interface,
3366 enum dcerpc_transport_t transport,
3367 enum pipe_auth_level auth_level,
3368 const char *domain,
3369 struct rpc_pipe_client **presult)
3371 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3372 struct rpc_pipe_client *netlogon_pipe = NULL;
3373 struct rpc_pipe_client *result = NULL;
3374 NTSTATUS status;
3376 *presult = NULL;
3378 status = get_schannel_session_key(cli, domain, &neg_flags,
3379 &netlogon_pipe);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3382 "key from server %s for domain %s.\n",
3383 cli->desthost, domain ));
3384 return status;
3387 status = cli_rpc_pipe_open_schannel_with_key(
3388 cli, interface, transport, auth_level, domain, netlogon_pipe->dc,
3389 &result);
3391 /* Now we've bound using the session key we can close the netlog pipe. */
3392 TALLOC_FREE(netlogon_pipe);
3394 if (NT_STATUS_IS_OK(status)) {
3395 *presult = result;
3398 return status;
3401 /****************************************************************************
3402 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3403 The idea is this can be called with service_princ, username and password all
3404 NULL so long as the caller has a TGT.
3405 ****************************************************************************/
3407 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3408 const struct ndr_syntax_id *interface,
3409 enum pipe_auth_level auth_level,
3410 const char *service_princ,
3411 const char *username,
3412 const char *password,
3413 struct rpc_pipe_client **presult)
3415 #ifdef HAVE_KRB5
3416 struct rpc_pipe_client *result;
3417 struct cli_pipe_auth_data *auth;
3418 NTSTATUS status;
3420 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 return status;
3425 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3426 username, password, &auth);
3427 if (!NT_STATUS_IS_OK(status)) {
3428 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3429 nt_errstr(status)));
3430 TALLOC_FREE(result);
3431 return status;
3434 status = rpc_pipe_bind(result, auth);
3435 if (!NT_STATUS_IS_OK(status)) {
3436 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3437 "with error %s\n", nt_errstr(status)));
3438 TALLOC_FREE(result);
3439 return status;
3442 *presult = result;
3443 return NT_STATUS_OK;
3444 #else
3445 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3446 return NT_STATUS_NOT_IMPLEMENTED;
3447 #endif
3450 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3451 struct rpc_pipe_client *cli,
3452 DATA_BLOB *session_key)
3454 if (!session_key || !cli) {
3455 return NT_STATUS_INVALID_PARAMETER;
3458 if (!cli->auth) {
3459 return NT_STATUS_INVALID_PARAMETER;
3462 switch (cli->auth->auth_type) {
3463 case PIPE_AUTH_TYPE_SCHANNEL:
3464 *session_key = data_blob_talloc(mem_ctx,
3465 cli->auth->a_u.schannel_auth->sess_key, 16);
3466 break;
3467 case PIPE_AUTH_TYPE_NTLMSSP:
3468 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3469 *session_key = data_blob_talloc(mem_ctx,
3470 cli->auth->a_u.ntlmssp_state->session_key.data,
3471 cli->auth->a_u.ntlmssp_state->session_key.length);
3472 break;
3473 case PIPE_AUTH_TYPE_KRB5:
3474 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3475 *session_key = data_blob_talloc(mem_ctx,
3476 cli->auth->a_u.kerberos_auth->session_key.data,
3477 cli->auth->a_u.kerberos_auth->session_key.length);
3478 break;
3479 case PIPE_AUTH_TYPE_NONE:
3480 default:
3481 return NT_STATUS_NO_USER_SESSION_KEY;
3484 return NT_STATUS_OK;