s3-rpc_client: fix rpccli_set_timeout to cope with abstract transport.
[Samba.git] / source / rpc_client / cli_pipe.c
blobbe84c3934ff97a33ef6bc9e57a7a9d74529065c0
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_CLI
26 /*******************************************************************
27 interface/version dce/rpc pipe identification
28 ********************************************************************/
30 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
31 #define PIPE_SAMR "\\PIPE\\samr"
32 #define PIPE_WINREG "\\PIPE\\winreg"
33 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
34 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
35 #define PIPE_NTLSA "\\PIPE\\ntlsa"
36 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
37 #define PIPE_LSASS "\\PIPE\\lsass"
38 #define PIPE_LSARPC "\\PIPE\\lsarpc"
39 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
40 #define PIPE_NETDFS "\\PIPE\\netdfs"
41 #define PIPE_ECHO "\\PIPE\\rpcecho"
42 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
43 #define PIPE_EPM "\\PIPE\\epmapper"
44 #define PIPE_SVCCTL "\\PIPE\\svcctl"
45 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
46 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
47 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
50 * IMPORTANT!! If you update this structure, make sure to
51 * update the index #defines in smb.h.
54 static const struct pipe_id_info {
55 /* the names appear not to matter: the syntaxes _do_ matter */
57 const char *client_pipe;
58 const RPC_IFACE *abstr_syntax; /* this one is the abstract syntax id */
59 } pipe_names [] =
61 { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
62 { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
63 { PIPE_SAMR, &ndr_table_samr.syntax_id },
64 { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
65 { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
66 { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
67 { PIPE_WINREG, &ndr_table_winreg.syntax_id },
68 { PIPE_SPOOLSS, &syntax_spoolss },
69 { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
70 { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
71 { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
72 { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
73 { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
74 { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
75 { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
76 { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
77 { NULL, NULL }
80 /****************************************************************************
81 Return the pipe name from the interface.
82 ****************************************************************************/
84 const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx,
85 struct cli_state *cli,
86 const struct ndr_syntax_id *interface)
88 int i;
89 for (i = 0; pipe_names[i].client_pipe; i++) {
90 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
91 interface)) {
92 return &pipe_names[i].client_pipe[5];
97 * Here we should ask \\epmapper, but for now our code is only
98 * interested in the known pipes mentioned in pipe_names[]
101 return NULL;
104 /********************************************************************
105 Map internal value to wire value.
106 ********************************************************************/
108 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
110 switch (auth_type) {
112 case PIPE_AUTH_TYPE_NONE:
113 return RPC_ANONYMOUS_AUTH_TYPE;
115 case PIPE_AUTH_TYPE_NTLMSSP:
116 return RPC_NTLMSSP_AUTH_TYPE;
118 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
119 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
120 return RPC_SPNEGO_AUTH_TYPE;
122 case PIPE_AUTH_TYPE_SCHANNEL:
123 return RPC_SCHANNEL_AUTH_TYPE;
125 case PIPE_AUTH_TYPE_KRB5:
126 return RPC_KRB5_AUTH_TYPE;
128 default:
129 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
130 "auth type %u\n",
131 (unsigned int)auth_type ));
132 break;
134 return -1;
137 /********************************************************************
138 Pipe description for a DEBUG
139 ********************************************************************/
140 static char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli)
142 char *result;
144 switch (cli->transport_type) {
145 case NCACN_NP:
146 result = talloc_asprintf(mem_ctx, "host %s, pipe %s, "
147 "fnum 0x%x",
148 cli->desthost,
149 cli->trans.np.pipe_name,
150 (unsigned int)(cli->trans.np.fnum));
151 break;
152 case NCACN_IP_TCP:
153 case NCACN_UNIX_STREAM:
154 result = talloc_asprintf(mem_ctx, "host %s, fd %d",
155 cli->desthost, cli->trans.sock.fd);
156 break;
157 default:
158 result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
159 break;
161 SMB_ASSERT(result != NULL);
162 return result;
165 /********************************************************************
166 Rpc pipe call id.
167 ********************************************************************/
169 static uint32 get_rpc_call_id(void)
171 static uint32 call_id = 0;
172 return ++call_id;
175 /*******************************************************************
176 Read from a RPC named pipe
177 ********************************************************************/
178 static NTSTATUS rpc_read_np(struct cli_state *cli, const char *pipe_name,
179 int fnum, char *buf, off_t offset, size_t size,
180 ssize_t *pnum_read)
182 ssize_t num_read;
184 num_read = cli_read(cli, fnum, buf, offset, size);
186 DEBUG(5,("rpc_read_np: num_read = %d, read offset: %u, to read: %u\n",
187 (int)num_read, (unsigned int)offset, (unsigned int)size));
190 * A dos error of ERRDOS/ERRmoredata is not an error.
192 if (cli_is_dos_error(cli)) {
193 uint32 ecode;
194 uint8 eclass;
195 cli_dos_error(cli, &eclass, &ecode);
196 if (eclass != ERRDOS && ecode != ERRmoredata) {
197 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read "
198 "on fnum 0x%x\n", eclass, (unsigned int)ecode,
199 cli_errstr(cli), fnum));
200 return dos_to_ntstatus(eclass, ecode);
205 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
207 if (cli_is_nt_error(cli)) {
208 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
209 NT_STATUS_BUFFER_TOO_SMALL)) {
210 DEBUG(0,("rpc_read: Error (%s) in cli_read on fnum "
211 "0x%x\n", nt_errstr(cli_nt_error(cli)), fnum));
212 return cli_nt_error(cli);
216 if (num_read == -1) {
217 DEBUG(0,("rpc_read: Error - cli_read on fnum 0x%x returned "
218 "-1\n", fnum));
219 return cli_get_nt_error(cli);
222 *pnum_read = num_read;
223 return NT_STATUS_OK;
227 /*******************************************************************
228 Use SMBreadX to get rest of one fragment's worth of rpc data.
229 Will expand the current_pdu struct to the correct size.
230 ********************************************************************/
232 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
233 prs_struct *current_pdu,
234 uint32 data_to_read,
235 uint32 *current_pdu_offset)
237 size_t size = (size_t)cli->max_recv_frag;
238 uint32 stream_offset = 0;
239 ssize_t num_read = 0;
240 char *pdata;
241 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
243 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
244 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
247 * Grow the buffer if needed to accommodate the data to be read.
250 if (extra_data_size > 0) {
251 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
252 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
253 return NT_STATUS_NO_MEMORY;
255 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
258 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
260 do {
261 NTSTATUS status;
263 /* read data using SMBreadX */
264 if (size > (size_t)data_to_read) {
265 size = (size_t)data_to_read;
268 switch (cli->transport_type) {
269 case NCACN_NP:
270 status = rpc_read_np(cli->trans.np.cli,
271 cli->trans.np.pipe_name,
272 cli->trans.np.fnum, pdata,
273 (off_t)stream_offset, size,
274 &num_read);
275 break;
276 case NCACN_IP_TCP:
277 case NCACN_UNIX_STREAM:
278 status = NT_STATUS_OK;
279 num_read = sys_read(cli->trans.sock.fd, pdata, size);
280 if (num_read == -1) {
281 status = map_nt_error_from_unix(errno);
283 if (num_read == 0) {
284 status = NT_STATUS_END_OF_FILE;
286 break;
287 default:
288 DEBUG(0, ("unknown transport type %d\n",
289 cli->transport_type));
290 return NT_STATUS_INTERNAL_ERROR;
293 data_to_read -= num_read;
294 stream_offset += num_read;
295 pdata += num_read;
297 } while (num_read > 0 && data_to_read > 0);
298 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
301 * Update the current offset into current_pdu by the amount read.
303 *current_pdu_offset += stream_offset;
304 return NT_STATUS_OK;
307 /****************************************************************************
308 Try and get a PDU's worth of data from current_pdu. If not, then read more
309 from the wire.
310 ****************************************************************************/
312 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
314 NTSTATUS ret = NT_STATUS_OK;
315 uint32 current_pdu_len = prs_data_size(current_pdu);
317 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
318 if (current_pdu_len < RPC_HEADER_LEN) {
319 /* rpc_read expands the current_pdu struct as neccessary. */
320 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
321 if (!NT_STATUS_IS_OK(ret)) {
322 return ret;
326 /* This next call sets the endian bit correctly in current_pdu. */
327 /* We will propagate this to rbuf later. */
328 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
329 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
330 return NT_STATUS_BUFFER_TOO_SMALL;
333 /* Ensure we have frag_len bytes of data. */
334 if (current_pdu_len < prhdr->frag_len) {
335 /* rpc_read expands the current_pdu struct as neccessary. */
336 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
337 if (!NT_STATUS_IS_OK(ret)) {
338 return ret;
342 if (current_pdu_len < prhdr->frag_len) {
343 return NT_STATUS_BUFFER_TOO_SMALL;
346 return NT_STATUS_OK;
349 /****************************************************************************
350 NTLMSSP specific sign/seal.
351 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
352 In fact I should probably abstract these into identical pieces of code... JRA.
353 ****************************************************************************/
355 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
356 prs_struct *current_pdu,
357 uint8 *p_ss_padding_len)
359 RPC_HDR_AUTH auth_info;
360 uint32 save_offset = prs_offset(current_pdu);
361 uint32 auth_len = prhdr->auth_len;
362 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
363 unsigned char *data = NULL;
364 size_t data_len;
365 unsigned char *full_packet_data = NULL;
366 size_t full_packet_data_len;
367 DATA_BLOB auth_blob;
368 NTSTATUS status;
370 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
371 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
372 return NT_STATUS_OK;
375 if (!ntlmssp_state) {
376 return NT_STATUS_INVALID_PARAMETER;
379 /* Ensure there's enough data for an authenticated response. */
380 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
381 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
382 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
383 (unsigned int)auth_len ));
384 return NT_STATUS_BUFFER_TOO_SMALL;
388 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
389 * after the RPC header.
390 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
391 * functions as NTLMv2 checks the rpc headers also.
394 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
395 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
397 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
398 full_packet_data_len = prhdr->frag_len - auth_len;
400 /* Pull the auth header and the following data into a blob. */
401 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
402 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
403 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
404 return NT_STATUS_BUFFER_TOO_SMALL;
407 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
408 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
409 return NT_STATUS_BUFFER_TOO_SMALL;
412 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
413 auth_blob.length = auth_len;
415 switch (cli->auth->auth_level) {
416 case PIPE_AUTH_LEVEL_PRIVACY:
417 /* Data is encrypted. */
418 status = ntlmssp_unseal_packet(ntlmssp_state,
419 data, data_len,
420 full_packet_data,
421 full_packet_data_len,
422 &auth_blob);
423 if (!NT_STATUS_IS_OK(status)) {
424 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
425 "packet from %s. Error was %s.\n",
426 rpccli_pipe_txt(debug_ctx(), cli),
427 nt_errstr(status) ));
428 return status;
430 break;
431 case PIPE_AUTH_LEVEL_INTEGRITY:
432 /* Data is signed. */
433 status = ntlmssp_check_packet(ntlmssp_state,
434 data, data_len,
435 full_packet_data,
436 full_packet_data_len,
437 &auth_blob);
438 if (!NT_STATUS_IS_OK(status)) {
439 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
440 "packet from %s. Error was %s.\n",
441 rpccli_pipe_txt(debug_ctx(), cli),
442 nt_errstr(status) ));
443 return status;
445 break;
446 default:
447 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
448 "auth level %d\n", cli->auth->auth_level));
449 return NT_STATUS_INVALID_INFO_CLASS;
453 * Return the current pointer to the data offset.
456 if(!prs_set_offset(current_pdu, save_offset)) {
457 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
458 (unsigned int)save_offset ));
459 return NT_STATUS_BUFFER_TOO_SMALL;
463 * Remember the padding length. We must remove it from the real data
464 * stream once the sign/seal is done.
467 *p_ss_padding_len = auth_info.auth_pad_len;
469 return NT_STATUS_OK;
472 /****************************************************************************
473 schannel specific sign/seal.
474 ****************************************************************************/
476 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
477 prs_struct *current_pdu,
478 uint8 *p_ss_padding_len)
480 RPC_HDR_AUTH auth_info;
481 RPC_AUTH_SCHANNEL_CHK schannel_chk;
482 uint32 auth_len = prhdr->auth_len;
483 uint32 save_offset = prs_offset(current_pdu);
484 struct schannel_auth_struct *schannel_auth =
485 cli->auth->a_u.schannel_auth;
486 uint32 data_len;
488 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
489 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
490 return NT_STATUS_OK;
493 if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
494 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
495 return NT_STATUS_INVALID_PARAMETER;
498 if (!schannel_auth) {
499 return NT_STATUS_INVALID_PARAMETER;
502 /* Ensure there's enough data for an authenticated response. */
503 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
504 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
505 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
506 (unsigned int)auth_len ));
507 return NT_STATUS_INVALID_PARAMETER;
510 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
512 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
513 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
514 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
515 return NT_STATUS_BUFFER_TOO_SMALL;
518 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
519 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
520 return NT_STATUS_BUFFER_TOO_SMALL;
523 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
524 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
525 auth_info.auth_type));
526 return NT_STATUS_BUFFER_TOO_SMALL;
529 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
530 &schannel_chk, current_pdu, 0)) {
531 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
532 return NT_STATUS_BUFFER_TOO_SMALL;
535 if (!schannel_decode(schannel_auth,
536 cli->auth->auth_level,
537 SENDER_IS_ACCEPTOR,
538 &schannel_chk,
539 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
540 data_len)) {
541 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
542 "Connection to %s.\n",
543 rpccli_pipe_txt(debug_ctx(), cli)));
544 return NT_STATUS_INVALID_PARAMETER;
547 /* The sequence number gets incremented on both send and receive. */
548 schannel_auth->seq_num++;
551 * Return the current pointer to the data offset.
554 if(!prs_set_offset(current_pdu, save_offset)) {
555 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
556 (unsigned int)save_offset ));
557 return NT_STATUS_BUFFER_TOO_SMALL;
561 * Remember the padding length. We must remove it from the real data
562 * stream once the sign/seal is done.
565 *p_ss_padding_len = auth_info.auth_pad_len;
567 return NT_STATUS_OK;
570 /****************************************************************************
571 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
572 ****************************************************************************/
574 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
575 prs_struct *current_pdu,
576 uint8 *p_ss_padding_len)
578 NTSTATUS ret = NT_STATUS_OK;
580 /* Paranioa checks for auth_len. */
581 if (prhdr->auth_len) {
582 if (prhdr->auth_len > prhdr->frag_len) {
583 return NT_STATUS_INVALID_PARAMETER;
586 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
587 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
588 /* Integer wrap attempt. */
589 return NT_STATUS_INVALID_PARAMETER;
594 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
597 switch(cli->auth->auth_type) {
598 case PIPE_AUTH_TYPE_NONE:
599 if (prhdr->auth_len) {
600 DEBUG(3, ("cli_pipe_validate_rpc_response: "
601 "Connection to %s - got non-zero "
602 "auth len %u.\n",
603 rpccli_pipe_txt(debug_ctx(), cli),
604 (unsigned int)prhdr->auth_len ));
605 return NT_STATUS_INVALID_PARAMETER;
607 break;
609 case PIPE_AUTH_TYPE_NTLMSSP:
610 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
611 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
612 if (!NT_STATUS_IS_OK(ret)) {
613 return ret;
615 break;
617 case PIPE_AUTH_TYPE_SCHANNEL:
618 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
619 if (!NT_STATUS_IS_OK(ret)) {
620 return ret;
622 break;
624 case PIPE_AUTH_TYPE_KRB5:
625 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
626 default:
627 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
628 "to %s - unknown internal auth type %u.\n",
629 rpccli_pipe_txt(debug_ctx(), cli),
630 cli->auth->auth_type ));
631 return NT_STATUS_INVALID_INFO_CLASS;
634 return NT_STATUS_OK;
637 /****************************************************************************
638 Do basic authentication checks on an incoming pdu.
639 ****************************************************************************/
641 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
642 prs_struct *current_pdu,
643 uint8 expected_pkt_type,
644 char **ppdata,
645 uint32 *pdata_len,
646 prs_struct *return_data)
649 NTSTATUS ret = NT_STATUS_OK;
650 uint32 current_pdu_len = prs_data_size(current_pdu);
652 if (current_pdu_len != prhdr->frag_len) {
653 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
654 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
655 return NT_STATUS_INVALID_PARAMETER;
659 * Point the return values at the real data including the RPC
660 * header. Just in case the caller wants it.
662 *ppdata = prs_data_p(current_pdu);
663 *pdata_len = current_pdu_len;
665 /* Ensure we have the correct type. */
666 switch (prhdr->pkt_type) {
667 case RPC_ALTCONTRESP:
668 case RPC_BINDACK:
670 /* Alter context and bind ack share the same packet definitions. */
671 break;
674 case RPC_RESPONSE:
676 RPC_HDR_RESP rhdr_resp;
677 uint8 ss_padding_len = 0;
679 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
680 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
681 return NT_STATUS_BUFFER_TOO_SMALL;
684 /* Here's where we deal with incoming sign/seal. */
685 ret = cli_pipe_validate_rpc_response(cli, prhdr,
686 current_pdu, &ss_padding_len);
687 if (!NT_STATUS_IS_OK(ret)) {
688 return ret;
691 /* Point the return values at the NDR data. Remember to remove any ss padding. */
692 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
694 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
695 return NT_STATUS_BUFFER_TOO_SMALL;
698 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
700 /* Remember to remove the auth footer. */
701 if (prhdr->auth_len) {
702 /* We've already done integer wrap tests on auth_len in
703 cli_pipe_validate_rpc_response(). */
704 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
705 return NT_STATUS_BUFFER_TOO_SMALL;
707 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
710 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
711 current_pdu_len, *pdata_len, ss_padding_len ));
714 * If this is the first reply, and the allocation hint is reasonably, try and
715 * set up the return_data parse_struct to the correct size.
718 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
719 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
720 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
721 "too large to allocate\n",
722 (unsigned int)rhdr_resp.alloc_hint ));
723 return NT_STATUS_NO_MEMORY;
727 break;
730 case RPC_BINDNACK:
731 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
732 "received from %s!\n",
733 rpccli_pipe_txt(debug_ctx(), cli)));
734 /* Use this for now... */
735 return NT_STATUS_NETWORK_ACCESS_DENIED;
737 case RPC_FAULT:
739 RPC_HDR_RESP rhdr_resp;
740 RPC_HDR_FAULT fault_resp;
742 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
743 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
744 return NT_STATUS_BUFFER_TOO_SMALL;
747 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
748 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
749 return NT_STATUS_BUFFER_TOO_SMALL;
752 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
753 "code %s received from %s!\n",
754 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
755 rpccli_pipe_txt(debug_ctx(), cli)));
756 if (NT_STATUS_IS_OK(fault_resp.status)) {
757 return NT_STATUS_UNSUCCESSFUL;
758 } else {
759 return fault_resp.status;
763 default:
764 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
765 "from %s!\n",
766 (unsigned int)prhdr->pkt_type,
767 rpccli_pipe_txt(debug_ctx(), cli)));
768 return NT_STATUS_INVALID_INFO_CLASS;
771 if (prhdr->pkt_type != expected_pkt_type) {
772 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
773 "got an unexpected RPC packet type - %u, not %u\n",
774 rpccli_pipe_txt(debug_ctx(), cli),
775 prhdr->pkt_type,
776 expected_pkt_type));
777 return NT_STATUS_INVALID_INFO_CLASS;
780 /* Do this just before return - we don't want to modify any rpc header
781 data before now as we may have needed to do cryptographic actions on
782 it before. */
784 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
785 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
786 "setting fragment first/last ON.\n"));
787 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
790 return NT_STATUS_OK;
793 /****************************************************************************
794 Ensure we eat the just processed pdu from the current_pdu prs_struct.
795 Normally the frag_len and buffer size will match, but on the first trans
796 reply there is a theoretical chance that buffer size > frag_len, so we must
797 deal with that.
798 ****************************************************************************/
800 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
802 uint32 current_pdu_len = prs_data_size(current_pdu);
804 if (current_pdu_len < prhdr->frag_len) {
805 return NT_STATUS_BUFFER_TOO_SMALL;
808 /* Common case. */
809 if (current_pdu_len == (uint32)prhdr->frag_len) {
810 prs_mem_free(current_pdu);
811 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
812 /* Make current_pdu dynamic with no memory. */
813 prs_give_memory(current_pdu, 0, 0, True);
814 return NT_STATUS_OK;
818 * Oh no ! More data in buffer than we processed in current pdu.
819 * Cheat. Move the data down and shrink the buffer.
822 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
823 current_pdu_len - prhdr->frag_len);
825 /* Remember to set the read offset back to zero. */
826 prs_set_offset(current_pdu, 0);
828 /* Shrink the buffer. */
829 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
830 return NT_STATUS_BUFFER_TOO_SMALL;
833 return NT_STATUS_OK;
836 /****************************************************************************
837 Send data on an rpc pipe via trans. The prs_struct data must be the last
838 pdu fragment of an NDR data stream.
840 Receive response data from an rpc pipe, which may be large...
842 Read the first fragment: unfortunately have to use SMBtrans for the first
843 bit, then SMBreadX for subsequent bits.
845 If first fragment received also wasn't the last fragment, continue
846 getting fragments until we _do_ receive the last fragment.
848 Request/Response PDU's look like the following...
850 |<------------------PDU len----------------------------------------------->|
851 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
853 +------------+-----------------+-------------+---------------+-------------+
854 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
855 +------------+-----------------+-------------+---------------+-------------+
857 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
858 signing & sealing being negotiated.
860 ****************************************************************************/
862 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
863 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
864 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
865 uint8 expected_pkt_type)
867 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
868 char *rparam = NULL;
869 uint32 rparam_len = 0;
870 char *pdata = prs_data_p(data);
871 uint32 data_len = prs_offset(data);
872 char *prdata = NULL;
873 uint32 rdata_len = 0;
874 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
875 uint32 current_rbuf_offset = 0;
876 prs_struct current_pdu;
878 #ifdef DEVELOPER
879 /* Ensure we're not sending too much. */
880 SMB_ASSERT(data_len <= max_data);
881 #endif
883 /* Set up the current pdu parse struct. */
884 prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
886 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
888 switch (cli->transport_type) {
889 case NCACN_NP: {
890 uint16 setup[2];
891 /* Create setup parameters - must be in native byte order. */
892 setup[0] = TRANSACT_DCERPCCMD;
893 setup[1] = cli->trans.np.fnum; /* Pipe file handle. */
896 * Send the last (or only) fragment of an RPC request. For
897 * small amounts of data (about 1024 bytes or so) the RPC
898 * request and response appears in a SMBtrans request and
899 * response.
902 if (!cli_api_pipe(cli->trans.np.cli, "\\PIPE\\",
903 setup, 2, 0, /* Setup, length, max */
904 NULL, 0, 0, /* Params, length, max */
905 pdata, data_len, max_data, /* data, length,
906 * max */
907 &rparam, &rparam_len, /* return params,
908 * len */
909 &prdata, &rdata_len)) /* return data, len */
911 DEBUG(0, ("rpc_api_pipe: %s returned critical error. "
912 "Error was %s\n",
913 rpccli_pipe_txt(debug_ctx(), cli),
914 cli_errstr(cli->trans.np.cli)));
915 ret = cli_get_nt_error(cli->trans.np.cli);
916 SAFE_FREE(rparam);
917 SAFE_FREE(prdata);
918 goto err;
920 break;
922 case NCACN_IP_TCP:
923 case NCACN_UNIX_STREAM:
925 ssize_t nwritten, nread;
926 nwritten = write_data(cli->trans.sock.fd, pdata, data_len);
927 if (nwritten == -1) {
928 ret = map_nt_error_from_unix(errno);
929 DEBUG(0, ("rpc_api_pipe: write_data returned %s\n",
930 strerror(errno)));
931 goto err;
933 rparam = NULL;
934 prdata = SMB_MALLOC_ARRAY(char, 1);
935 if (prdata == NULL) {
936 return NT_STATUS_NO_MEMORY;
938 nread = sys_read(cli->trans.sock.fd, prdata, 1);
939 if (nread == 0) {
940 SAFE_FREE(prdata);
942 if (nread == -1) {
943 ret = NT_STATUS_END_OF_FILE;
944 goto err;
946 rdata_len = nread;
947 break;
949 default:
950 DEBUG(0, ("unknown transport type %d\n",
951 cli->transport_type));
952 return NT_STATUS_INTERNAL_ERROR;
955 /* Throw away returned params - we know we won't use them. */
957 SAFE_FREE(rparam);
959 if (prdata == NULL) {
960 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
961 rpccli_pipe_txt(debug_ctx(), cli)));
962 /* Yes - some calls can truely return no data... */
963 prs_mem_free(&current_pdu);
964 return NT_STATUS_OK;
968 * Give this memory as dynamic to the current pdu.
971 prs_give_memory(&current_pdu, prdata, rdata_len, True);
973 /* Ensure we can mess with the return prs_struct. */
974 SMB_ASSERT(UNMARSHALLING(rbuf));
975 SMB_ASSERT(prs_data_size(rbuf) == 0);
977 /* Make rbuf dynamic with no memory. */
978 prs_give_memory(rbuf, 0, 0, True);
980 while(1) {
981 RPC_HDR rhdr;
982 char *ret_data = NULL;
983 uint32 ret_data_len = 0;
985 /* Ensure we have enough data for a pdu. */
986 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
987 if (!NT_STATUS_IS_OK(ret)) {
988 goto err;
991 /* We pass in rbuf here so if the alloc hint is set correctly
992 we can set the output size and avoid reallocs. */
994 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
995 &ret_data, &ret_data_len, rbuf);
997 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
998 prs_data_size(&current_pdu), current_rbuf_offset ));
1000 if (!NT_STATUS_IS_OK(ret)) {
1001 goto err;
1004 if ((rhdr.flags & RPC_FLG_FIRST)) {
1005 if (rhdr.pack_type[0] == 0) {
1006 /* Set the data type correctly for big-endian data on the first packet. */
1007 DEBUG(10,("rpc_api_pipe: On %s "
1008 "PDU data format is big-endian.\n",
1009 rpccli_pipe_txt(debug_ctx(), cli)));
1011 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
1012 } else {
1013 /* Check endianness on subsequent packets. */
1014 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
1015 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
1016 rbuf->bigendian_data ? "big" : "little",
1017 current_pdu.bigendian_data ? "big" : "little" ));
1018 ret = NT_STATUS_INVALID_PARAMETER;
1019 goto err;
1024 /* Now copy the data portion out of the pdu into rbuf. */
1025 if (!prs_force_grow(rbuf, ret_data_len)) {
1026 ret = NT_STATUS_NO_MEMORY;
1027 goto err;
1029 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
1030 current_rbuf_offset += ret_data_len;
1032 /* See if we've finished with all the data in current_pdu yet ? */
1033 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
1034 if (!NT_STATUS_IS_OK(ret)) {
1035 goto err;
1038 if (rhdr.flags & RPC_FLG_LAST) {
1039 break; /* We're done. */
1043 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1044 rpccli_pipe_txt(debug_ctx(), cli),
1045 (unsigned int)prs_data_size(rbuf) ));
1047 prs_mem_free(&current_pdu);
1048 return NT_STATUS_OK;
1050 err:
1052 prs_mem_free(&current_pdu);
1053 prs_mem_free(rbuf);
1054 return ret;
1057 /*******************************************************************
1058 Creates krb5 auth bind.
1059 ********************************************************************/
1061 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1062 enum pipe_auth_level auth_level,
1063 RPC_HDR_AUTH *pauth_out,
1064 prs_struct *auth_data)
1066 #ifdef HAVE_KRB5
1067 int ret;
1068 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1069 DATA_BLOB tkt = data_blob_null;
1070 DATA_BLOB tkt_wrapped = data_blob_null;
1072 /* We may change the pad length before marshalling. */
1073 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
1075 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1076 a->service_principal ));
1078 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1080 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1081 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
1083 if (ret) {
1084 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1085 "failed with %s\n",
1086 a->service_principal,
1087 error_message(ret) ));
1089 data_blob_free(&tkt);
1090 prs_mem_free(auth_data);
1091 return NT_STATUS_INVALID_PARAMETER;
1094 /* wrap that up in a nice GSS-API wrapping */
1095 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1097 data_blob_free(&tkt);
1099 /* Auth len in the rpc header doesn't include auth_header. */
1100 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1101 data_blob_free(&tkt_wrapped);
1102 prs_mem_free(auth_data);
1103 return NT_STATUS_NO_MEMORY;
1106 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1107 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1109 data_blob_free(&tkt_wrapped);
1110 return NT_STATUS_OK;
1111 #else
1112 return NT_STATUS_INVALID_PARAMETER;
1113 #endif
1116 /*******************************************************************
1117 Creates SPNEGO NTLMSSP auth bind.
1118 ********************************************************************/
1120 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1121 enum pipe_auth_level auth_level,
1122 RPC_HDR_AUTH *pauth_out,
1123 prs_struct *auth_data)
1125 NTSTATUS nt_status;
1126 DATA_BLOB null_blob = data_blob_null;
1127 DATA_BLOB request = data_blob_null;
1128 DATA_BLOB spnego_msg = data_blob_null;
1130 /* We may change the pad length before marshalling. */
1131 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1133 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1134 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1135 null_blob,
1136 &request);
1138 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1139 data_blob_free(&request);
1140 prs_mem_free(auth_data);
1141 return nt_status;
1144 /* Wrap this in SPNEGO. */
1145 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1147 data_blob_free(&request);
1149 /* Auth len in the rpc header doesn't include auth_header. */
1150 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1151 data_blob_free(&spnego_msg);
1152 prs_mem_free(auth_data);
1153 return NT_STATUS_NO_MEMORY;
1156 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1157 dump_data(5, spnego_msg.data, spnego_msg.length);
1159 data_blob_free(&spnego_msg);
1160 return NT_STATUS_OK;
1163 /*******************************************************************
1164 Creates NTLMSSP auth bind.
1165 ********************************************************************/
1167 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1168 enum pipe_auth_level auth_level,
1169 RPC_HDR_AUTH *pauth_out,
1170 prs_struct *auth_data)
1172 NTSTATUS nt_status;
1173 DATA_BLOB null_blob = data_blob_null;
1174 DATA_BLOB request = data_blob_null;
1176 /* We may change the pad length before marshalling. */
1177 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1179 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1180 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1181 null_blob,
1182 &request);
1184 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1185 data_blob_free(&request);
1186 prs_mem_free(auth_data);
1187 return nt_status;
1190 /* Auth len in the rpc header doesn't include auth_header. */
1191 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1192 data_blob_free(&request);
1193 prs_mem_free(auth_data);
1194 return NT_STATUS_NO_MEMORY;
1197 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1198 dump_data(5, request.data, request.length);
1200 data_blob_free(&request);
1201 return NT_STATUS_OK;
1204 /*******************************************************************
1205 Creates schannel auth bind.
1206 ********************************************************************/
1208 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1209 enum pipe_auth_level auth_level,
1210 RPC_HDR_AUTH *pauth_out,
1211 prs_struct *auth_data)
1213 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1215 /* We may change the pad length before marshalling. */
1216 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1218 /* Use lp_workgroup() if domain not specified */
1220 if (!cli->auth->domain || !cli->auth->domain[0]) {
1221 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1222 if (cli->auth->domain == NULL) {
1223 return NT_STATUS_NO_MEMORY;
1227 init_rpc_auth_schannel_neg(&schannel_neg, cli->auth->domain,
1228 global_myname());
1231 * Now marshall the data into the auth parse_struct.
1234 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1235 &schannel_neg, auth_data, 0)) {
1236 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1237 prs_mem_free(auth_data);
1238 return NT_STATUS_NO_MEMORY;
1241 return NT_STATUS_OK;
1244 /*******************************************************************
1245 Creates the internals of a DCE/RPC bind request or alter context PDU.
1246 ********************************************************************/
1248 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1249 prs_struct *rpc_out,
1250 uint32 rpc_call_id,
1251 const RPC_IFACE *abstract,
1252 const RPC_IFACE *transfer,
1253 RPC_HDR_AUTH *phdr_auth,
1254 prs_struct *pauth_info)
1256 RPC_HDR hdr;
1257 RPC_HDR_RB hdr_rb;
1258 RPC_CONTEXT rpc_ctx;
1259 uint16 auth_len = prs_offset(pauth_info);
1260 uint8 ss_padding_len = 0;
1261 uint16 frag_len = 0;
1263 /* create the RPC context. */
1264 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1266 /* create the bind request RPC_HDR_RB */
1267 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1269 /* Start building the frag length. */
1270 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1272 /* Do we need to pad ? */
1273 if (auth_len) {
1274 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1275 if (data_len % 8) {
1276 ss_padding_len = 8 - (data_len % 8);
1277 phdr_auth->auth_pad_len = ss_padding_len;
1279 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1282 /* Create the request RPC_HDR */
1283 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1285 /* Marshall the RPC header */
1286 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1287 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1288 return NT_STATUS_NO_MEMORY;
1291 /* Marshall the bind request data */
1292 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1293 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1294 return NT_STATUS_NO_MEMORY;
1298 * Grow the outgoing buffer to store any auth info.
1301 if(auth_len != 0) {
1302 if (ss_padding_len) {
1303 char pad[8];
1304 memset(pad, '\0', 8);
1305 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1306 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1307 return NT_STATUS_NO_MEMORY;
1311 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1312 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1313 return NT_STATUS_NO_MEMORY;
1317 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1318 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1319 return NT_STATUS_NO_MEMORY;
1323 return NT_STATUS_OK;
1326 /*******************************************************************
1327 Creates a DCE/RPC bind request.
1328 ********************************************************************/
1330 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1331 prs_struct *rpc_out,
1332 uint32 rpc_call_id,
1333 const RPC_IFACE *abstract,
1334 const RPC_IFACE *transfer,
1335 enum pipe_auth_type auth_type,
1336 enum pipe_auth_level auth_level)
1338 RPC_HDR_AUTH hdr_auth;
1339 prs_struct auth_info;
1340 NTSTATUS ret = NT_STATUS_OK;
1342 ZERO_STRUCT(hdr_auth);
1343 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1344 return NT_STATUS_NO_MEMORY;
1346 switch (auth_type) {
1347 case PIPE_AUTH_TYPE_SCHANNEL:
1348 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1349 if (!NT_STATUS_IS_OK(ret)) {
1350 prs_mem_free(&auth_info);
1351 return ret;
1353 break;
1355 case PIPE_AUTH_TYPE_NTLMSSP:
1356 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1357 if (!NT_STATUS_IS_OK(ret)) {
1358 prs_mem_free(&auth_info);
1359 return ret;
1361 break;
1363 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1364 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1365 if (!NT_STATUS_IS_OK(ret)) {
1366 prs_mem_free(&auth_info);
1367 return ret;
1369 break;
1371 case PIPE_AUTH_TYPE_KRB5:
1372 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1373 if (!NT_STATUS_IS_OK(ret)) {
1374 prs_mem_free(&auth_info);
1375 return ret;
1377 break;
1379 case PIPE_AUTH_TYPE_NONE:
1380 break;
1382 default:
1383 /* "Can't" happen. */
1384 return NT_STATUS_INVALID_INFO_CLASS;
1387 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1388 rpc_out,
1389 rpc_call_id,
1390 abstract,
1391 transfer,
1392 &hdr_auth,
1393 &auth_info);
1395 prs_mem_free(&auth_info);
1396 return ret;
1399 /*******************************************************************
1400 Create and add the NTLMSSP sign/seal auth header and data.
1401 ********************************************************************/
1403 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1404 RPC_HDR *phdr,
1405 uint32 ss_padding_len,
1406 prs_struct *outgoing_pdu)
1408 RPC_HDR_AUTH auth_info;
1409 NTSTATUS status;
1410 DATA_BLOB auth_blob = data_blob_null;
1411 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1413 if (!cli->auth->a_u.ntlmssp_state) {
1414 return NT_STATUS_INVALID_PARAMETER;
1417 /* Init and marshall the auth header. */
1418 init_rpc_hdr_auth(&auth_info,
1419 map_pipe_auth_type_to_rpc_auth_type(
1420 cli->auth->auth_type),
1421 cli->auth->auth_level,
1422 ss_padding_len,
1423 1 /* context id. */);
1425 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1426 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1427 data_blob_free(&auth_blob);
1428 return NT_STATUS_NO_MEMORY;
1431 switch (cli->auth->auth_level) {
1432 case PIPE_AUTH_LEVEL_PRIVACY:
1433 /* Data portion is encrypted. */
1434 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1435 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1436 data_and_pad_len,
1437 (unsigned char *)prs_data_p(outgoing_pdu),
1438 (size_t)prs_offset(outgoing_pdu),
1439 &auth_blob);
1440 if (!NT_STATUS_IS_OK(status)) {
1441 data_blob_free(&auth_blob);
1442 return status;
1444 break;
1446 case PIPE_AUTH_LEVEL_INTEGRITY:
1447 /* Data is signed. */
1448 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1449 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1450 data_and_pad_len,
1451 (unsigned char *)prs_data_p(outgoing_pdu),
1452 (size_t)prs_offset(outgoing_pdu),
1453 &auth_blob);
1454 if (!NT_STATUS_IS_OK(status)) {
1455 data_blob_free(&auth_blob);
1456 return status;
1458 break;
1460 default:
1461 /* Can't happen. */
1462 smb_panic("bad auth level");
1463 /* Notreached. */
1464 return NT_STATUS_INVALID_PARAMETER;
1467 /* Finally marshall the blob. */
1469 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1470 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1471 (unsigned int)NTLMSSP_SIG_SIZE));
1472 data_blob_free(&auth_blob);
1473 return NT_STATUS_NO_MEMORY;
1476 data_blob_free(&auth_blob);
1477 return NT_STATUS_OK;
1480 /*******************************************************************
1481 Create and add the schannel sign/seal auth header and data.
1482 ********************************************************************/
1484 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1485 RPC_HDR *phdr,
1486 uint32 ss_padding_len,
1487 prs_struct *outgoing_pdu)
1489 RPC_HDR_AUTH auth_info;
1490 RPC_AUTH_SCHANNEL_CHK verf;
1491 struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
1492 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1493 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1495 if (!sas) {
1496 return NT_STATUS_INVALID_PARAMETER;
1499 /* Init and marshall the auth header. */
1500 init_rpc_hdr_auth(&auth_info,
1501 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1502 cli->auth->auth_level,
1503 ss_padding_len,
1504 1 /* context id. */);
1506 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1507 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1508 return NT_STATUS_NO_MEMORY;
1511 switch (cli->auth->auth_level) {
1512 case PIPE_AUTH_LEVEL_PRIVACY:
1513 case PIPE_AUTH_LEVEL_INTEGRITY:
1514 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1515 sas->seq_num));
1517 schannel_encode(sas,
1518 cli->auth->auth_level,
1519 SENDER_IS_INITIATOR,
1520 &verf,
1521 data_p,
1522 data_and_pad_len);
1524 sas->seq_num++;
1525 break;
1527 default:
1528 /* Can't happen. */
1529 smb_panic("bad auth level");
1530 /* Notreached. */
1531 return NT_STATUS_INVALID_PARAMETER;
1534 /* Finally marshall the blob. */
1535 smb_io_rpc_auth_schannel_chk("",
1536 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1537 &verf,
1538 outgoing_pdu,
1541 return NT_STATUS_OK;
1544 /*******************************************************************
1545 Calculate how much data we're going to send in this packet, also
1546 work out any sign/seal padding length.
1547 ********************************************************************/
1549 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1550 uint32 data_left,
1551 uint16 *p_frag_len,
1552 uint16 *p_auth_len,
1553 uint32 *p_ss_padding)
1555 uint32 data_space, data_len;
1557 switch (cli->auth->auth_level) {
1558 case PIPE_AUTH_LEVEL_NONE:
1559 case PIPE_AUTH_LEVEL_CONNECT:
1560 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1561 data_len = MIN(data_space, data_left);
1562 *p_ss_padding = 0;
1563 *p_auth_len = 0;
1564 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1565 return data_len;
1567 case PIPE_AUTH_LEVEL_INTEGRITY:
1568 case PIPE_AUTH_LEVEL_PRIVACY:
1569 /* Treat the same for all authenticated rpc requests. */
1570 switch(cli->auth->auth_type) {
1571 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1572 case PIPE_AUTH_TYPE_NTLMSSP:
1573 *p_auth_len = NTLMSSP_SIG_SIZE;
1574 break;
1575 case PIPE_AUTH_TYPE_SCHANNEL:
1576 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1577 break;
1578 default:
1579 smb_panic("bad auth type");
1580 break;
1583 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1584 RPC_HDR_AUTH_LEN - *p_auth_len;
1586 data_len = MIN(data_space, data_left);
1587 if (data_len % 8) {
1588 *p_ss_padding = 8 - (data_len % 8);
1590 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1591 data_len + *p_ss_padding + /* data plus padding. */
1592 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1593 return data_len;
1595 default:
1596 smb_panic("bad auth level");
1597 /* Notreached. */
1598 return 0;
1602 /*******************************************************************
1603 External interface.
1604 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1605 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1606 and deals with signing/sealing details.
1607 ********************************************************************/
1609 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1610 uint8 op_num,
1611 prs_struct *in_data,
1612 prs_struct *out_data)
1614 NTSTATUS ret;
1615 uint32 data_left = prs_offset(in_data);
1616 uint32 alloc_hint = prs_offset(in_data);
1617 uint32 data_sent_thistime = 0;
1618 uint32 current_data_offset = 0;
1619 uint32 call_id = get_rpc_call_id();
1620 char pad[8];
1621 prs_struct outgoing_pdu;
1623 memset(pad, '\0', 8);
1625 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1626 /* Server is screwed up ! */
1627 return NT_STATUS_INVALID_PARAMETER;
1630 if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1631 return NT_STATUS_NO_MEMORY;
1633 while (1) {
1634 RPC_HDR hdr;
1635 RPC_HDR_REQ hdr_req;
1636 uint16 auth_len = 0;
1637 uint16 frag_len = 0;
1638 uint8 flags = 0;
1639 uint32 ss_padding = 0;
1641 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1642 &frag_len, &auth_len, &ss_padding);
1644 if (current_data_offset == 0) {
1645 flags = RPC_FLG_FIRST;
1648 if (data_sent_thistime == data_left) {
1649 flags |= RPC_FLG_LAST;
1652 /* Create and marshall the header and request header. */
1653 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1655 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1656 prs_mem_free(&outgoing_pdu);
1657 return NT_STATUS_NO_MEMORY;
1660 /* Create the rpc request RPC_HDR_REQ */
1661 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1663 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1664 prs_mem_free(&outgoing_pdu);
1665 return NT_STATUS_NO_MEMORY;
1668 /* Copy in the data, plus any ss padding. */
1669 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1670 prs_mem_free(&outgoing_pdu);
1671 return NT_STATUS_NO_MEMORY;
1674 /* Copy the sign/seal padding data. */
1675 if (ss_padding) {
1676 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1677 prs_mem_free(&outgoing_pdu);
1678 return NT_STATUS_NO_MEMORY;
1682 /* Generate any auth sign/seal and add the auth footer. */
1683 if (auth_len) {
1684 switch (cli->auth->auth_type) {
1685 case PIPE_AUTH_TYPE_NONE:
1686 break;
1687 case PIPE_AUTH_TYPE_NTLMSSP:
1688 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1689 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1690 if (!NT_STATUS_IS_OK(ret)) {
1691 prs_mem_free(&outgoing_pdu);
1692 return ret;
1694 break;
1695 case PIPE_AUTH_TYPE_SCHANNEL:
1696 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1697 if (!NT_STATUS_IS_OK(ret)) {
1698 prs_mem_free(&outgoing_pdu);
1699 return ret;
1701 break;
1702 default:
1703 smb_panic("bad auth type");
1704 break; /* notreached */
1708 /* Actually send the packet. */
1709 if (flags & RPC_FLG_LAST) {
1710 /* Last packet - send the data, get the reply and return. */
1711 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1712 prs_mem_free(&outgoing_pdu);
1714 if ((DEBUGLEVEL >= 50)
1715 && (cli->transport_type == NCACN_NP)) {
1716 char *dump_name = NULL;
1717 /* Also capture received data */
1718 if (asprintf(&dump_name, "%s/reply_%s_%d",
1719 get_dyn_LOGFILEBASE(),
1720 cli->trans.np.pipe_name, op_num) > 0) {
1721 prs_dump(dump_name, op_num, out_data);
1722 SAFE_FREE(dump_name);
1726 return ret;
1727 } else {
1728 /* More packets to come - write and continue. */
1729 ssize_t num_written;
1731 switch (cli->transport_type) {
1732 case NCACN_NP:
1733 num_written = cli_write(cli->trans.np.cli,
1734 cli->trans.np.fnum,
1735 8, /* 8 means message mode. */
1736 prs_data_p(&outgoing_pdu),
1737 (off_t)0,
1738 (size_t)hdr.frag_len);
1740 if (num_written != hdr.frag_len) {
1741 prs_mem_free(&outgoing_pdu);
1742 return cli_get_nt_error(
1743 cli->trans.np.cli);
1745 break;
1746 case NCACN_IP_TCP:
1747 case NCACN_UNIX_STREAM:
1748 num_written = write_data(
1749 cli->trans.sock.fd,
1750 prs_data_p(&outgoing_pdu),
1751 (size_t)hdr.frag_len);
1752 if (num_written != hdr.frag_len) {
1753 NTSTATUS status;
1754 status = map_nt_error_from_unix(errno);
1755 prs_mem_free(&outgoing_pdu);
1756 return status;
1758 break;
1759 default:
1760 DEBUG(0, ("unknown transport type %d\n",
1761 cli->transport_type));
1762 return NT_STATUS_INTERNAL_ERROR;
1766 current_data_offset += data_sent_thistime;
1767 data_left -= data_sent_thistime;
1769 /* Reset the marshalling position back to zero. */
1770 if (!prs_set_offset(&outgoing_pdu, 0)) {
1771 prs_mem_free(&outgoing_pdu);
1772 return NT_STATUS_NO_MEMORY;
1776 #if 0
1777 /****************************************************************************
1778 Set the handle state.
1779 ****************************************************************************/
1781 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1782 const char *pipe_name, uint16 device_state)
1784 bool state_set = False;
1785 char param[2];
1786 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1787 char *rparam = NULL;
1788 char *rdata = NULL;
1789 uint32 rparam_len, rdata_len;
1791 if (pipe_name == NULL)
1792 return False;
1794 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1795 cli->fnum, pipe_name, device_state));
1797 /* create parameters: device state */
1798 SSVAL(param, 0, device_state);
1800 /* create setup parameters. */
1801 setup[0] = 0x0001;
1802 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1804 /* send the data on \PIPE\ */
1805 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1806 setup, 2, 0, /* setup, length, max */
1807 param, 2, 0, /* param, length, max */
1808 NULL, 0, 1024, /* data, length, max */
1809 &rparam, &rparam_len, /* return param, length */
1810 &rdata, &rdata_len)) /* return data, length */
1812 DEBUG(5, ("Set Handle state: return OK\n"));
1813 state_set = True;
1816 SAFE_FREE(rparam);
1817 SAFE_FREE(rdata);
1819 return state_set;
1821 #endif
1823 /****************************************************************************
1824 Check the rpc bind acknowledge response.
1825 ****************************************************************************/
1827 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1829 if ( hdr_ba->addr.len == 0) {
1830 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1833 /* check the transfer syntax */
1834 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1835 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1836 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1837 return False;
1840 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1841 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1842 hdr_ba->res.num_results, hdr_ba->res.reason));
1845 DEBUG(5,("check_bind_response: accepted!\n"));
1846 return True;
1849 /*******************************************************************
1850 Creates a DCE/RPC bind authentication response.
1851 This is the packet that is sent back to the server once we
1852 have received a BIND-ACK, to finish the third leg of
1853 the authentication handshake.
1854 ********************************************************************/
1856 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1857 uint32 rpc_call_id,
1858 enum pipe_auth_type auth_type,
1859 enum pipe_auth_level auth_level,
1860 DATA_BLOB *pauth_blob,
1861 prs_struct *rpc_out)
1863 RPC_HDR hdr;
1864 RPC_HDR_AUTH hdr_auth;
1865 uint32 pad = 0;
1867 /* Create the request RPC_HDR */
1868 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1869 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1870 pauth_blob->length );
1872 /* Marshall it. */
1873 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1874 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1875 return NT_STATUS_NO_MEMORY;
1879 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1880 about padding - shouldn't this pad to length 8 ? JRA.
1883 /* 4 bytes padding. */
1884 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1885 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1886 return NT_STATUS_NO_MEMORY;
1889 /* Create the request RPC_HDR_AUTHA */
1890 init_rpc_hdr_auth(&hdr_auth,
1891 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1892 auth_level, 0, 1);
1894 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1895 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1896 return NT_STATUS_NO_MEMORY;
1900 * Append the auth data to the outgoing buffer.
1903 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1904 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1905 return NT_STATUS_NO_MEMORY;
1908 return NT_STATUS_OK;
1911 /****************************************************************************
1912 Create and send the third packet in an RPC auth.
1913 ****************************************************************************/
1915 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1916 RPC_HDR *phdr,
1917 prs_struct *rbuf,
1918 uint32 rpc_call_id,
1919 enum pipe_auth_type auth_type,
1920 enum pipe_auth_level auth_level)
1922 DATA_BLOB server_response = data_blob_null;
1923 DATA_BLOB client_reply = data_blob_null;
1924 RPC_HDR_AUTH hdr_auth;
1925 NTSTATUS nt_status;
1926 prs_struct rpc_out;
1927 ssize_t ret;
1929 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1930 return NT_STATUS_INVALID_PARAMETER;
1933 /* Process the returned NTLMSSP blob first. */
1934 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1935 return NT_STATUS_INVALID_PARAMETER;
1938 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1939 return NT_STATUS_INVALID_PARAMETER;
1942 /* TODO - check auth_type/auth_level match. */
1944 server_response = data_blob(NULL, phdr->auth_len);
1945 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1947 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1948 server_response,
1949 &client_reply);
1951 if (!NT_STATUS_IS_OK(nt_status)) {
1952 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1953 data_blob_free(&server_response);
1954 return nt_status;
1957 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1959 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1960 auth_type, auth_level,
1961 &client_reply, &rpc_out);
1963 if (!NT_STATUS_IS_OK(nt_status)) {
1964 prs_mem_free(&rpc_out);
1965 data_blob_free(&client_reply);
1966 data_blob_free(&server_response);
1967 return nt_status;
1970 switch (cli->transport_type) {
1971 case NCACN_NP:
1972 /* 8 here is named pipe message mode. */
1973 ret = cli_write(cli->trans.np.cli, cli->trans.np.fnum,
1974 0x8, prs_data_p(&rpc_out), 0,
1975 (size_t)prs_offset(&rpc_out));
1976 break;
1978 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1979 nt_status = cli_get_nt_error(cli->trans.np.cli);
1981 case NCACN_IP_TCP:
1982 case NCACN_UNIX_STREAM:
1983 ret = write_data(cli->trans.sock.fd, prs_data_p(&rpc_out),
1984 (size_t)prs_offset(&rpc_out));
1985 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1986 nt_status = map_nt_error_from_unix(errno);
1988 break;
1989 default:
1990 DEBUG(0, ("unknown transport type %d\n", cli->transport_type));
1991 return NT_STATUS_INTERNAL_ERROR;
1994 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1995 DEBUG(0,("rpc_send_auth_auth3: write failed. Return was %s\n",
1996 nt_errstr(nt_status)));
1997 prs_mem_free(&rpc_out);
1998 data_blob_free(&client_reply);
1999 data_blob_free(&server_response);
2000 return nt_status;
2003 DEBUG(5,("rpc_send_auth_auth3: %s sent auth3 response ok.\n",
2004 rpccli_pipe_txt(debug_ctx(), cli)));
2006 prs_mem_free(&rpc_out);
2007 data_blob_free(&client_reply);
2008 data_blob_free(&server_response);
2009 return NT_STATUS_OK;
2012 /*******************************************************************
2013 Creates a DCE/RPC bind alter context authentication request which
2014 may contain a spnego auth blobl
2015 ********************************************************************/
2017 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2018 const RPC_IFACE *abstract,
2019 const RPC_IFACE *transfer,
2020 enum pipe_auth_level auth_level,
2021 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2022 prs_struct *rpc_out)
2024 RPC_HDR_AUTH hdr_auth;
2025 prs_struct auth_info;
2026 NTSTATUS ret = NT_STATUS_OK;
2028 ZERO_STRUCT(hdr_auth);
2029 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2030 return NT_STATUS_NO_MEMORY;
2032 /* We may change the pad length before marshalling. */
2033 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
2035 if (pauth_blob->length) {
2036 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2037 prs_mem_free(&auth_info);
2038 return NT_STATUS_NO_MEMORY;
2042 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
2043 rpc_out,
2044 rpc_call_id,
2045 abstract,
2046 transfer,
2047 &hdr_auth,
2048 &auth_info);
2049 prs_mem_free(&auth_info);
2050 return ret;
2053 /*******************************************************************
2054 Third leg of the SPNEGO bind mechanism - sends alter context PDU
2055 and gets a response.
2056 ********************************************************************/
2058 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
2059 RPC_HDR *phdr,
2060 prs_struct *rbuf,
2061 uint32 rpc_call_id,
2062 const RPC_IFACE *abstract,
2063 const RPC_IFACE *transfer,
2064 enum pipe_auth_type auth_type,
2065 enum pipe_auth_level auth_level)
2067 DATA_BLOB server_spnego_response = data_blob_null;
2068 DATA_BLOB server_ntlm_response = data_blob_null;
2069 DATA_BLOB client_reply = data_blob_null;
2070 DATA_BLOB tmp_blob = data_blob_null;
2071 RPC_HDR_AUTH hdr_auth;
2072 NTSTATUS nt_status;
2073 prs_struct rpc_out;
2075 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2076 return NT_STATUS_INVALID_PARAMETER;
2079 /* Process the returned NTLMSSP blob first. */
2080 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2081 return NT_STATUS_INVALID_PARAMETER;
2084 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2085 return NT_STATUS_INVALID_PARAMETER;
2088 server_spnego_response = data_blob(NULL, phdr->auth_len);
2089 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2091 /* The server might give us back two challenges - tmp_blob is for the second. */
2092 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
2093 data_blob_free(&server_spnego_response);
2094 data_blob_free(&server_ntlm_response);
2095 data_blob_free(&tmp_blob);
2096 return NT_STATUS_INVALID_PARAMETER;
2099 /* We're finished with the server spnego response and the tmp_blob. */
2100 data_blob_free(&server_spnego_response);
2101 data_blob_free(&tmp_blob);
2103 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
2104 server_ntlm_response,
2105 &client_reply);
2107 /* Finished with the server_ntlm response */
2108 data_blob_free(&server_ntlm_response);
2110 if (!NT_STATUS_IS_OK(nt_status)) {
2111 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
2112 data_blob_free(&client_reply);
2113 return nt_status;
2116 /* SPNEGO wrap the client reply. */
2117 tmp_blob = spnego_gen_auth(client_reply);
2118 data_blob_free(&client_reply);
2119 client_reply = tmp_blob;
2120 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
2122 /* Now prepare the alter context pdu. */
2123 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
2125 nt_status = create_rpc_alter_context(rpc_call_id,
2126 abstract,
2127 transfer,
2128 auth_level,
2129 &client_reply,
2130 &rpc_out);
2132 data_blob_free(&client_reply);
2134 if (!NT_STATUS_IS_OK(nt_status)) {
2135 prs_mem_free(&rpc_out);
2136 return nt_status;
2139 /* Initialize the returning data struct. */
2140 prs_mem_free(rbuf);
2141 prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
2143 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
2144 if (!NT_STATUS_IS_OK(nt_status)) {
2145 prs_mem_free(&rpc_out);
2146 return nt_status;
2149 prs_mem_free(&rpc_out);
2151 /* Get the auth blob from the reply. */
2152 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
2153 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
2154 return NT_STATUS_BUFFER_TOO_SMALL;
2157 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2158 return NT_STATUS_INVALID_PARAMETER;
2161 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2162 return NT_STATUS_INVALID_PARAMETER;
2165 server_spnego_response = data_blob(NULL, phdr->auth_len);
2166 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2168 /* Check we got a valid auth response. */
2169 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
2170 data_blob_free(&server_spnego_response);
2171 data_blob_free(&tmp_blob);
2172 return NT_STATUS_INVALID_PARAMETER;
2175 data_blob_free(&server_spnego_response);
2176 data_blob_free(&tmp_blob);
2178 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2179 "%s.\n", rpccli_pipe_txt(debug_ctx(), cli)));
2181 return NT_STATUS_OK;
2184 /****************************************************************************
2185 Do an rpc bind.
2186 ****************************************************************************/
2188 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2189 struct cli_pipe_auth_data *auth)
2191 RPC_HDR hdr;
2192 RPC_HDR_BA hdr_ba;
2193 prs_struct rpc_out;
2194 prs_struct rbuf;
2195 uint32 rpc_call_id;
2196 NTSTATUS status;
2198 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2199 rpccli_pipe_txt(debug_ctx(), cli),
2200 (unsigned int)auth->auth_type,
2201 (unsigned int)auth->auth_level ));
2203 cli->auth = talloc_move(cli, &auth);
2205 prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2207 rpc_call_id = get_rpc_call_id();
2209 /* Marshall the outgoing data. */
2210 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2211 &cli->abstract_syntax,
2212 &cli->transfer_syntax,
2213 cli->auth->auth_type,
2214 cli->auth->auth_level);
2216 if (!NT_STATUS_IS_OK(status)) {
2217 prs_mem_free(&rpc_out);
2218 return status;
2221 /* Initialize the incoming data struct. */
2222 prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2224 /* send data on \PIPE\. receive a response */
2225 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2226 if (!NT_STATUS_IS_OK(status)) {
2227 prs_mem_free(&rpc_out);
2228 return status;
2231 prs_mem_free(&rpc_out);
2233 DEBUG(3,("rpc_pipe_bind: %s bind request returned ok.\n",
2234 rpccli_pipe_txt(debug_ctx(), cli)));
2236 /* Unmarshall the RPC header */
2237 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2238 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2239 prs_mem_free(&rbuf);
2240 return NT_STATUS_BUFFER_TOO_SMALL;
2243 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2244 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2245 prs_mem_free(&rbuf);
2246 return NT_STATUS_BUFFER_TOO_SMALL;
2249 if(!check_bind_response(&hdr_ba, &cli->transfer_syntax)) {
2250 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2251 prs_mem_free(&rbuf);
2252 return NT_STATUS_BUFFER_TOO_SMALL;
2255 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2256 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2258 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2259 switch(cli->auth->auth_type) {
2261 case PIPE_AUTH_TYPE_NONE:
2262 case PIPE_AUTH_TYPE_SCHANNEL:
2263 /* Bind complete. */
2264 break;
2266 case PIPE_AUTH_TYPE_NTLMSSP:
2267 /* Need to send AUTH3 packet - no reply. */
2268 status = rpc_finish_auth3_bind(
2269 cli, &hdr, &rbuf, rpc_call_id,
2270 cli->auth->auth_type,
2271 cli->auth->auth_level);
2272 if (!NT_STATUS_IS_OK(status)) {
2273 prs_mem_free(&rbuf);
2274 return status;
2276 break;
2278 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2279 /* Need to send alter context request and reply. */
2280 status = rpc_finish_spnego_ntlmssp_bind(
2281 cli, &hdr, &rbuf, rpc_call_id,
2282 &cli->abstract_syntax, &cli->transfer_syntax,
2283 cli->auth->auth_type, cli->auth->auth_level);
2284 if (!NT_STATUS_IS_OK(status)) {
2285 prs_mem_free(&rbuf);
2286 return status;
2288 break;
2290 case PIPE_AUTH_TYPE_KRB5:
2291 /* */
2293 default:
2294 DEBUG(0,("cli_finish_bind_auth: unknown auth type "
2295 "%u\n", (unsigned int)cli->auth->auth_type));
2296 prs_mem_free(&rbuf);
2297 return NT_STATUS_INVALID_INFO_CLASS;
2300 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2301 if (cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP
2302 || cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2303 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2304 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2305 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2306 prs_mem_free(&rbuf);
2307 return NT_STATUS_INVALID_PARAMETER;
2310 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2311 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2312 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2313 prs_mem_free(&rbuf);
2314 return NT_STATUS_INVALID_PARAMETER;
2319 prs_mem_free(&rbuf);
2320 return NT_STATUS_OK;
2322 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2323 unsigned int timeout)
2325 struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
2327 if (cli == NULL) {
2328 return 0;
2330 return cli_set_timeout(cli, timeout);
2333 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16])
2335 if ((cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2336 || (cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2337 memcpy(nt_hash, cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2338 return true;
2341 if (cli->transport_type == NCACN_NP) {
2342 E_md4hash(cli->trans.np.cli->pwd.password, nt_hash);
2343 return true;
2346 return false;
2349 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
2351 if (p->transport_type == NCACN_NP) {
2352 return p->trans.np.cli;
2354 return NULL;
2357 static int rpc_pipe_destructor(struct rpc_pipe_client *p)
2359 if (p->transport_type == NCACN_NP) {
2360 bool ret;
2361 ret = cli_close(p->trans.np.cli, p->trans.np.fnum);
2362 if (!ret) {
2363 DEBUG(1, ("rpc_pipe_destructor: cli_close failed on "
2364 "pipe %s. Error was %s\n",
2365 rpccli_pipe_txt(debug_ctx(), p),
2366 cli_errstr(p->trans.np.cli)));
2369 DEBUG(10, ("rpc_pipe_destructor: closed %s\n",
2370 rpccli_pipe_txt(debug_ctx(), p)));
2372 DLIST_REMOVE(p->trans.np.cli->pipe_list, p);
2373 return ret ? -1 : 0;
2376 return -1;
2379 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2380 struct cli_pipe_auth_data **presult)
2382 struct cli_pipe_auth_data *result;
2384 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2385 if (result == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2389 result->auth_type = PIPE_AUTH_TYPE_NONE;
2390 result->auth_level = PIPE_AUTH_LEVEL_NONE;
2392 result->user_name = talloc_strdup(result, "");
2393 result->domain = talloc_strdup(result, "");
2394 if ((result->user_name == NULL) || (result->domain == NULL)) {
2395 TALLOC_FREE(result);
2396 return NT_STATUS_NO_MEMORY;
2399 *presult = result;
2400 return NT_STATUS_OK;
2403 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2405 ntlmssp_end(&auth->a_u.ntlmssp_state);
2406 return 0;
2409 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2410 enum pipe_auth_type auth_type,
2411 enum pipe_auth_level auth_level,
2412 const char *domain,
2413 const char *username,
2414 const char *password,
2415 struct cli_pipe_auth_data **presult)
2417 struct cli_pipe_auth_data *result;
2418 NTSTATUS status;
2420 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2421 if (result == NULL) {
2422 return NT_STATUS_NO_MEMORY;
2425 result->auth_type = auth_type;
2426 result->auth_level = auth_level;
2428 result->user_name = talloc_strdup(result, username);
2429 result->domain = talloc_strdup(result, domain);
2430 if ((result->user_name == NULL) || (result->domain == NULL)) {
2431 status = NT_STATUS_NO_MEMORY;
2432 goto fail;
2435 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 goto fail;
2440 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2442 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 goto fail;
2447 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2448 if (!NT_STATUS_IS_OK(status)) {
2449 goto fail;
2452 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2453 if (!NT_STATUS_IS_OK(status)) {
2454 goto fail;
2458 * Turn off sign+seal to allow selected auth level to turn it back on.
2460 result->a_u.ntlmssp_state->neg_flags &=
2461 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2463 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2464 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2465 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2466 result->a_u.ntlmssp_state->neg_flags
2467 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2470 *presult = result;
2471 return NT_STATUS_OK;
2473 fail:
2474 TALLOC_FREE(result);
2475 return status;
2478 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2479 enum pipe_auth_level auth_level,
2480 const uint8_t sess_key[16],
2481 struct cli_pipe_auth_data **presult)
2483 struct cli_pipe_auth_data *result;
2485 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2486 if (result == NULL) {
2487 return NT_STATUS_NO_MEMORY;
2490 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2491 result->auth_level = auth_level;
2493 result->user_name = talloc_strdup(result, "");
2494 result->domain = talloc_strdup(result, domain);
2495 if ((result->user_name == NULL) || (result->domain == NULL)) {
2496 goto fail;
2499 result->a_u.schannel_auth = talloc(result,
2500 struct schannel_auth_struct);
2501 if (result->a_u.schannel_auth == NULL) {
2502 goto fail;
2505 memcpy(result->a_u.schannel_auth->sess_key, sess_key,
2506 sizeof(result->a_u.schannel_auth->sess_key));
2507 result->a_u.schannel_auth->seq_num = 0;
2509 *presult = result;
2510 return NT_STATUS_OK;
2512 fail:
2513 TALLOC_FREE(result);
2514 return NT_STATUS_NO_MEMORY;
2517 #ifdef HAVE_KRB5
2518 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2520 data_blob_free(&auth->session_key);
2521 return 0;
2523 #endif
2525 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2526 enum pipe_auth_level auth_level,
2527 const char *service_princ,
2528 const char *username,
2529 const char *password,
2530 struct cli_pipe_auth_data **presult)
2532 #ifdef HAVE_KRB5
2533 struct cli_pipe_auth_data *result;
2535 if ((username != NULL) && (password != NULL)) {
2536 int ret = kerberos_kinit_password(username, password, 0, NULL);
2537 if (ret != 0) {
2538 return NT_STATUS_ACCESS_DENIED;
2542 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2543 if (result == NULL) {
2544 return NT_STATUS_NO_MEMORY;
2547 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2548 result->auth_level = auth_level;
2551 * Username / domain need fixing!
2553 result->user_name = talloc_strdup(result, "");
2554 result->domain = talloc_strdup(result, "");
2555 if ((result->user_name == NULL) || (result->domain == NULL)) {
2556 goto fail;
2559 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2560 result, struct kerberos_auth_struct);
2561 if (result->a_u.kerberos_auth == NULL) {
2562 goto fail;
2564 talloc_set_destructor(result->a_u.kerberos_auth,
2565 cli_auth_kerberos_data_destructor);
2567 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2568 result, service_princ);
2569 if (result->a_u.kerberos_auth->service_principal == NULL) {
2570 goto fail;
2573 *presult = result;
2574 return NT_STATUS_OK;
2576 fail:
2577 TALLOC_FREE(result);
2578 return NT_STATUS_NO_MEMORY;
2579 #else
2580 return NT_STATUS_NOT_SUPPORTED;
2581 #endif
2584 static int rpc_pipe_sock_destructor(struct rpc_pipe_client *p)
2586 close(p->trans.sock.fd);
2587 return 0;
2591 * Create an rpc pipe client struct, connecting to a tcp port.
2593 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2594 uint16_t port,
2595 const struct ndr_syntax_id *abstract_syntax,
2596 struct rpc_pipe_client **presult)
2598 struct rpc_pipe_client *result;
2599 struct sockaddr_storage addr;
2600 NTSTATUS status;
2602 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2603 if (result == NULL) {
2604 return NT_STATUS_NO_MEMORY;
2607 result->transport_type = NCACN_IP_TCP;
2609 result->abstract_syntax = *abstract_syntax;
2610 result->transfer_syntax = ndr_transfer_syntax;
2612 result->desthost = talloc_strdup(result, host);
2613 result->srv_name_slash = talloc_asprintf_strupper_m(
2614 result, "\\\\%s", result->desthost);
2615 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2616 status = NT_STATUS_NO_MEMORY;
2617 goto fail;
2620 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2621 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2623 if (!resolve_name(host, &addr, 0)) {
2624 status = NT_STATUS_NOT_FOUND;
2625 goto fail;
2628 result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60);
2629 if (result->trans.sock.fd == -1) {
2630 status = map_nt_error_from_unix(errno);
2631 goto fail;
2634 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2636 *presult = result;
2637 return NT_STATUS_OK;
2639 fail:
2640 TALLOC_FREE(result);
2641 return status;
2645 * Determine the tcp port on which a dcerpc interface is listening
2646 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2647 * target host.
2649 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2650 const struct ndr_syntax_id *abstract_syntax,
2651 uint16_t *pport)
2653 NTSTATUS status;
2654 struct rpc_pipe_client *epm_pipe = NULL;
2655 struct cli_pipe_auth_data *auth = NULL;
2656 struct dcerpc_binding *map_binding = NULL;
2657 struct dcerpc_binding *res_binding = NULL;
2658 struct epm_twr_t *map_tower = NULL;
2659 struct epm_twr_t *res_towers = NULL;
2660 struct policy_handle *entry_handle = NULL;
2661 uint32_t num_towers = 0;
2662 uint32_t max_towers = 1;
2663 struct epm_twr_p_t towers;
2664 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2666 if (pport == NULL) {
2667 status = NT_STATUS_INVALID_PARAMETER;
2668 goto done;
2671 /* open the connection to the endpoint mapper */
2672 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2673 &ndr_table_epmapper.syntax_id,
2674 &epm_pipe);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 goto done;
2680 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 goto done;
2685 status = rpc_pipe_bind(epm_pipe, auth);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 goto done;
2690 /* create tower for asking the epmapper */
2692 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2693 if (map_binding == NULL) {
2694 status = NT_STATUS_NO_MEMORY;
2695 goto done;
2698 map_binding->transport = NCACN_IP_TCP;
2699 map_binding->object = *abstract_syntax;
2700 map_binding->host = host; /* needed? */
2701 map_binding->endpoint = "0"; /* correct? needed? */
2703 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2704 if (map_tower == NULL) {
2705 status = NT_STATUS_NO_MEMORY;
2706 goto done;
2709 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2710 &(map_tower->tower));
2711 if (!NT_STATUS_IS_OK(status)) {
2712 goto done;
2715 /* allocate further parameters for the epm_Map call */
2717 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2718 if (res_towers == NULL) {
2719 status = NT_STATUS_NO_MEMORY;
2720 goto done;
2722 towers.twr = res_towers;
2724 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2725 if (entry_handle == NULL) {
2726 status = NT_STATUS_NO_MEMORY;
2727 goto done;
2730 /* ask the endpoint mapper for the port */
2732 status = rpccli_epm_Map(epm_pipe,
2733 tmp_ctx,
2734 CONST_DISCARD(struct GUID *,
2735 &(abstract_syntax->uuid)),
2736 map_tower,
2737 entry_handle,
2738 max_towers,
2739 &num_towers,
2740 &towers);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 goto done;
2746 if (num_towers != 1) {
2747 status = NT_STATUS_UNSUCCESSFUL;
2748 goto done;
2751 /* extract the port from the answer */
2753 status = dcerpc_binding_from_tower(tmp_ctx,
2754 &(towers.twr->tower),
2755 &res_binding);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 goto done;
2760 /* are further checks here necessary? */
2761 if (res_binding->transport != NCACN_IP_TCP) {
2762 status = NT_STATUS_UNSUCCESSFUL;
2763 goto done;
2766 *pport = (uint16_t)atoi(res_binding->endpoint);
2768 done:
2769 TALLOC_FREE(tmp_ctx);
2770 return status;
2774 * Create a rpc pipe client struct, connecting to a host via tcp.
2775 * The port is determined by asking the endpoint mapper on the given
2776 * host.
2778 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2779 const struct ndr_syntax_id *abstract_syntax,
2780 struct rpc_pipe_client **presult)
2782 NTSTATUS status;
2783 uint16_t port = 0;
2785 *presult = NULL;
2787 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 goto done;
2792 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
2793 abstract_syntax, presult);
2795 done:
2796 return status;
2799 /********************************************************************
2800 Create a rpc pipe client struct, connecting to a unix domain socket
2801 ********************************************************************/
2802 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2803 const struct ndr_syntax_id *abstract_syntax,
2804 struct rpc_pipe_client **presult)
2806 struct rpc_pipe_client *result;
2807 struct sockaddr_un addr;
2808 NTSTATUS status;
2810 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2811 if (result == NULL) {
2812 return NT_STATUS_NO_MEMORY;
2815 result->transport_type = NCACN_UNIX_STREAM;
2817 result->abstract_syntax = *abstract_syntax;
2818 result->transfer_syntax = ndr_transfer_syntax;
2820 result->desthost = get_myname(result);
2821 result->srv_name_slash = talloc_asprintf_strupper_m(
2822 result, "\\\\%s", result->desthost);
2823 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2824 status = NT_STATUS_NO_MEMORY;
2825 goto fail;
2828 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2829 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2831 result->trans.sock.fd = socket(AF_UNIX, SOCK_STREAM, 0);
2832 if (result->trans.sock.fd == -1) {
2833 status = map_nt_error_from_unix(errno);
2834 goto fail;
2837 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2839 ZERO_STRUCT(addr);
2840 addr.sun_family = AF_UNIX;
2841 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2843 if (sys_connect(result->trans.sock.fd,
2844 (struct sockaddr *)&addr) == -1) {
2845 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2846 strerror(errno)));
2847 close(result->trans.sock.fd);
2848 return map_nt_error_from_unix(errno);
2851 *presult = result;
2852 return NT_STATUS_OK;
2854 fail:
2855 TALLOC_FREE(result);
2856 return status;
2860 /****************************************************************************
2861 Open a named pipe over SMB to a remote server.
2863 * CAVEAT CALLER OF THIS FUNCTION:
2864 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2865 * so be sure that this function is called AFTER any structure (vs pointer)
2866 * assignment of the cli. In particular, libsmbclient does structure
2867 * assignments of cli, which invalidates the data in the returned
2868 * rpc_pipe_client if this function is called before the structure assignment
2869 * of cli.
2871 ****************************************************************************/
2873 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2874 const struct ndr_syntax_id *abstract_syntax,
2875 struct rpc_pipe_client **presult)
2877 struct rpc_pipe_client *result;
2878 int fnum;
2880 /* sanity check to protect against crashes */
2882 if ( !cli ) {
2883 return NT_STATUS_INVALID_HANDLE;
2886 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2887 if (result == NULL) {
2888 return NT_STATUS_NO_MEMORY;
2891 result->transport_type = NCACN_NP;
2893 result->trans.np.pipe_name = cli_get_pipe_name_from_iface(
2894 result, cli, abstract_syntax);
2895 if (result->trans.np.pipe_name == NULL) {
2896 DEBUG(1, ("Could not find pipe for interface\n"));
2897 TALLOC_FREE(result);
2898 return NT_STATUS_INVALID_PARAMETER;
2901 result->trans.np.cli = cli;
2902 result->abstract_syntax = *abstract_syntax;
2903 result->transfer_syntax = ndr_transfer_syntax;
2904 result->desthost = talloc_strdup(result, cli->desthost);
2905 result->srv_name_slash = talloc_asprintf_strupper_m(
2906 result, "\\\\%s", result->desthost);
2908 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2909 TALLOC_FREE(result);
2910 return NT_STATUS_NO_MEMORY;
2913 fnum = cli_nt_create(cli, result->trans.np.pipe_name,
2914 DESIRED_ACCESS_PIPE);
2915 if (fnum == -1) {
2916 DEBUG(3,("rpc_pipe_open_np: cli_nt_create failed on pipe %s "
2917 "to machine %s. Error was %s\n",
2918 result->trans.np.pipe_name, cli->desthost,
2919 cli_errstr(cli)));
2920 TALLOC_FREE(result);
2921 return cli_get_nt_error(cli);
2924 result->trans.np.fnum = fnum;
2926 DLIST_ADD(cli->pipe_list, result);
2927 talloc_set_destructor(result, rpc_pipe_destructor);
2929 *presult = result;
2930 return NT_STATUS_OK;
2933 /****************************************************************************
2934 Open a pipe to a remote server.
2935 ****************************************************************************/
2937 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2938 enum dcerpc_transport_t transport,
2939 const struct ndr_syntax_id *interface,
2940 struct rpc_pipe_client **presult)
2942 switch (transport) {
2943 case NCACN_IP_TCP:
2944 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2945 presult);
2946 case NCACN_NP:
2947 return rpc_pipe_open_np(cli, interface, presult);
2948 default:
2949 return NT_STATUS_NOT_IMPLEMENTED;
2953 /****************************************************************************
2954 Open a named pipe to an SMB server and bind anonymously.
2955 ****************************************************************************/
2957 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2958 enum dcerpc_transport_t transport,
2959 const struct ndr_syntax_id *interface,
2960 struct rpc_pipe_client **presult)
2962 struct rpc_pipe_client *result;
2963 struct cli_pipe_auth_data *auth;
2964 NTSTATUS status;
2966 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2967 if (!NT_STATUS_IS_OK(status)) {
2968 return status;
2971 status = rpccli_anon_bind_data(result, &auth);
2972 if (!NT_STATUS_IS_OK(status)) {
2973 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2974 nt_errstr(status)));
2975 TALLOC_FREE(result);
2976 return status;
2980 * This is a bit of an abstraction violation due to the fact that an
2981 * anonymous bind on an authenticated SMB inherits the user/domain
2982 * from the enclosing SMB creds
2985 TALLOC_FREE(auth->user_name);
2986 TALLOC_FREE(auth->domain);
2988 auth->user_name = talloc_strdup(auth, cli->user_name);
2989 auth->domain = talloc_strdup(auth, cli->domain);
2991 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2992 TALLOC_FREE(result);
2993 return NT_STATUS_NO_MEMORY;
2996 status = rpc_pipe_bind(result, auth);
2997 if (!NT_STATUS_IS_OK(status)) {
2998 int lvl = 0;
2999 if (ndr_syntax_id_equal(interface,
3000 &ndr_table_dssetup.syntax_id)) {
3001 /* non AD domains just don't have this pipe, avoid
3002 * level 0 statement in that case - gd */
3003 lvl = 3;
3005 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3006 "%s failed with error %s\n",
3007 cli_get_pipe_name_from_iface(debug_ctx(), cli,
3008 interface),
3009 nt_errstr(status) ));
3010 TALLOC_FREE(result);
3011 return status;
3014 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3015 "%s and bound anonymously.\n", result->trans.np.pipe_name,
3016 cli->desthost ));
3018 *presult = result;
3019 return NT_STATUS_OK;
3022 /****************************************************************************
3023 ****************************************************************************/
3025 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3026 const struct ndr_syntax_id *interface,
3027 struct rpc_pipe_client **presult)
3029 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3030 interface, presult);
3033 /****************************************************************************
3034 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3035 ****************************************************************************/
3037 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3038 const struct ndr_syntax_id *interface,
3039 enum dcerpc_transport_t transport,
3040 enum pipe_auth_type auth_type,
3041 enum pipe_auth_level auth_level,
3042 const char *domain,
3043 const char *username,
3044 const char *password,
3045 struct rpc_pipe_client **presult)
3047 struct rpc_pipe_client *result;
3048 struct cli_pipe_auth_data *auth;
3049 NTSTATUS status;
3051 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3052 if (!NT_STATUS_IS_OK(status)) {
3053 return status;
3056 status = rpccli_ntlmssp_bind_data(
3057 result, auth_type, auth_level, domain, username,
3058 cli->pwd.null_pwd ? NULL : password, &auth);
3059 if (!NT_STATUS_IS_OK(status)) {
3060 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3061 nt_errstr(status)));
3062 goto err;
3065 status = rpc_pipe_bind(result, auth);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3068 nt_errstr(status) ));
3069 goto err;
3072 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3073 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3074 result->trans.np.pipe_name, cli->desthost,
3075 domain, username ));
3077 *presult = result;
3078 return NT_STATUS_OK;
3080 err:
3082 TALLOC_FREE(result);
3083 return status;
3086 /****************************************************************************
3087 External interface.
3088 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3089 ****************************************************************************/
3091 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3092 const struct ndr_syntax_id *interface,
3093 enum dcerpc_transport_t transport,
3094 enum pipe_auth_level auth_level,
3095 const char *domain,
3096 const char *username,
3097 const char *password,
3098 struct rpc_pipe_client **presult)
3100 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3101 interface,
3102 transport,
3103 PIPE_AUTH_TYPE_NTLMSSP,
3104 auth_level,
3105 domain,
3106 username,
3107 password,
3108 presult);
3111 /****************************************************************************
3112 External interface.
3113 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3114 ****************************************************************************/
3116 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3117 const struct ndr_syntax_id *interface,
3118 enum dcerpc_transport_t transport,
3119 enum pipe_auth_level auth_level,
3120 const char *domain,
3121 const char *username,
3122 const char *password,
3123 struct rpc_pipe_client **presult)
3125 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3126 interface,
3127 transport,
3128 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3129 auth_level,
3130 domain,
3131 username,
3132 password,
3133 presult);
3136 /****************************************************************************
3137 Get a the schannel session key out of an already opened netlogon pipe.
3138 ****************************************************************************/
3139 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3140 struct cli_state *cli,
3141 const char *domain,
3142 uint32 *pneg_flags)
3144 uint32 sec_chan_type = 0;
3145 unsigned char machine_pwd[16];
3146 const char *machine_account;
3147 NTSTATUS status;
3149 /* Get the machine account credentials from secrets.tdb. */
3150 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3151 &sec_chan_type))
3153 DEBUG(0, ("get_schannel_session_key: could not fetch "
3154 "trust account password for domain '%s'\n",
3155 domain));
3156 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3159 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3160 cli->desthost, /* server name */
3161 domain, /* domain */
3162 global_myname(), /* client name */
3163 machine_account, /* machine account name */
3164 machine_pwd,
3165 sec_chan_type,
3166 pneg_flags);
3168 if (!NT_STATUS_IS_OK(status)) {
3169 DEBUG(3, ("get_schannel_session_key_common: "
3170 "rpccli_netlogon_setup_creds failed with result %s "
3171 "to server %s, domain %s, machine account %s.\n",
3172 nt_errstr(status), cli->desthost, domain,
3173 machine_account ));
3174 return status;
3177 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3178 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3179 cli->desthost));
3180 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3183 return NT_STATUS_OK;;
3186 /****************************************************************************
3187 Open a netlogon pipe and get the schannel session key.
3188 Now exposed to external callers.
3189 ****************************************************************************/
3192 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3193 const char *domain,
3194 uint32 *pneg_flags,
3195 struct rpc_pipe_client **presult)
3197 struct rpc_pipe_client *netlogon_pipe = NULL;
3198 NTSTATUS status;
3200 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3201 &netlogon_pipe);
3202 if (!NT_STATUS_IS_OK(status)) {
3203 return status;
3206 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3207 pneg_flags);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 TALLOC_FREE(netlogon_pipe);
3210 return status;
3213 *presult = netlogon_pipe;
3214 return NT_STATUS_OK;
3217 /****************************************************************************
3218 External interface.
3219 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3220 using session_key. sign and seal.
3221 ****************************************************************************/
3223 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3224 const struct ndr_syntax_id *interface,
3225 enum dcerpc_transport_t transport,
3226 enum pipe_auth_level auth_level,
3227 const char *domain,
3228 const struct dcinfo *pdc,
3229 struct rpc_pipe_client **presult)
3231 struct rpc_pipe_client *result;
3232 struct cli_pipe_auth_data *auth;
3233 NTSTATUS status;
3235 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 return status;
3240 status = rpccli_schannel_bind_data(result, domain, auth_level,
3241 pdc->sess_key, &auth);
3242 if (!NT_STATUS_IS_OK(status)) {
3243 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3244 nt_errstr(status)));
3245 TALLOC_FREE(result);
3246 return status;
3249 status = rpc_pipe_bind(result, auth);
3250 if (!NT_STATUS_IS_OK(status)) {
3251 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3252 "cli_rpc_pipe_bind failed with error %s\n",
3253 nt_errstr(status) ));
3254 TALLOC_FREE(result);
3255 return status;
3259 * The credentials on a new netlogon pipe are the ones we are passed
3260 * in - copy them over.
3262 result->dc = (struct dcinfo *)talloc_memdup(result, pdc, sizeof(*pdc));
3263 if (result->dc == NULL) {
3264 DEBUG(0, ("talloc failed\n"));
3265 TALLOC_FREE(result);
3266 return NT_STATUS_NO_MEMORY;
3269 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3270 "for domain %s "
3271 "and bound using schannel.\n",
3272 result->trans.np.pipe_name, cli->desthost, domain ));
3274 *presult = result;
3275 return NT_STATUS_OK;
3278 /****************************************************************************
3279 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3280 Fetch the session key ourselves using a temporary netlogon pipe. This
3281 version uses an ntlmssp auth bound netlogon pipe to get the key.
3282 ****************************************************************************/
3284 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3285 const char *domain,
3286 const char *username,
3287 const char *password,
3288 uint32 *pneg_flags,
3289 struct rpc_pipe_client **presult)
3291 struct rpc_pipe_client *netlogon_pipe = NULL;
3292 NTSTATUS status;
3294 status = cli_rpc_pipe_open_spnego_ntlmssp(
3295 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3296 PIPE_AUTH_LEVEL_PRIVACY,
3297 domain, username, password, &netlogon_pipe);
3298 if (!NT_STATUS_IS_OK(status)) {
3299 return status;
3302 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3303 pneg_flags);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 TALLOC_FREE(netlogon_pipe);
3306 return status;
3309 *presult = netlogon_pipe;
3310 return NT_STATUS_OK;
3313 /****************************************************************************
3314 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3315 Fetch the session key ourselves using a temporary netlogon pipe. This version
3316 uses an ntlmssp bind to get the session key.
3317 ****************************************************************************/
3319 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3320 const struct ndr_syntax_id *interface,
3321 enum dcerpc_transport_t transport,
3322 enum pipe_auth_level auth_level,
3323 const char *domain,
3324 const char *username,
3325 const char *password,
3326 struct rpc_pipe_client **presult)
3328 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3329 struct rpc_pipe_client *netlogon_pipe = NULL;
3330 struct rpc_pipe_client *result = NULL;
3331 NTSTATUS status;
3333 status = get_schannel_session_key_auth_ntlmssp(
3334 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3335 if (!NT_STATUS_IS_OK(status)) {
3336 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3337 "key from server %s for domain %s.\n",
3338 cli->desthost, domain ));
3339 return status;
3342 status = cli_rpc_pipe_open_schannel_with_key(
3343 cli, interface, transport, auth_level, domain, netlogon_pipe->dc,
3344 &result);
3346 /* Now we've bound using the session key we can close the netlog pipe. */
3347 TALLOC_FREE(netlogon_pipe);
3349 if (NT_STATUS_IS_OK(status)) {
3350 *presult = result;
3352 return status;
3355 /****************************************************************************
3356 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3357 Fetch the session key ourselves using a temporary netlogon pipe.
3358 ****************************************************************************/
3360 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3361 const struct ndr_syntax_id *interface,
3362 enum dcerpc_transport_t transport,
3363 enum pipe_auth_level auth_level,
3364 const char *domain,
3365 struct rpc_pipe_client **presult)
3367 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3368 struct rpc_pipe_client *netlogon_pipe = NULL;
3369 struct rpc_pipe_client *result = NULL;
3370 NTSTATUS status;
3372 status = get_schannel_session_key(cli, domain, &neg_flags,
3373 &netlogon_pipe);
3374 if (!NT_STATUS_IS_OK(status)) {
3375 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3376 "key from server %s for domain %s.\n",
3377 cli->desthost, domain ));
3378 return status;
3381 status = cli_rpc_pipe_open_schannel_with_key(
3382 cli, interface, transport, auth_level, domain, netlogon_pipe->dc,
3383 &result);
3385 /* Now we've bound using the session key we can close the netlog pipe. */
3386 TALLOC_FREE(netlogon_pipe);
3388 if (NT_STATUS_IS_OK(status)) {
3389 *presult = result;
3392 return NT_STATUS_OK;
3395 /****************************************************************************
3396 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3397 The idea is this can be called with service_princ, username and password all
3398 NULL so long as the caller has a TGT.
3399 ****************************************************************************/
3401 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3402 const struct ndr_syntax_id *interface,
3403 enum pipe_auth_level auth_level,
3404 const char *service_princ,
3405 const char *username,
3406 const char *password,
3407 struct rpc_pipe_client **presult)
3409 #ifdef HAVE_KRB5
3410 struct rpc_pipe_client *result;
3411 struct cli_pipe_auth_data *auth;
3412 NTSTATUS status;
3414 status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 return status;
3419 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3420 username, password, &auth);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3423 nt_errstr(status)));
3424 TALLOC_FREE(result);
3425 return status;
3428 status = rpc_pipe_bind(result, auth);
3429 if (!NT_STATUS_IS_OK(status)) {
3430 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3431 "with error %s\n", nt_errstr(status)));
3432 TALLOC_FREE(result);
3433 return status;
3436 *presult = result;
3437 return NT_STATUS_OK;
3438 #else
3439 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3440 return NT_STATUS_NOT_IMPLEMENTED;
3441 #endif
3444 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3445 struct rpc_pipe_client *cli,
3446 DATA_BLOB *session_key)
3448 if (!session_key || !cli) {
3449 return NT_STATUS_INVALID_PARAMETER;
3452 if (!cli->auth) {
3453 return NT_STATUS_INVALID_PARAMETER;
3456 switch (cli->auth->auth_type) {
3457 case PIPE_AUTH_TYPE_SCHANNEL:
3458 *session_key = data_blob_talloc(mem_ctx,
3459 cli->auth->a_u.schannel_auth->sess_key, 16);
3460 break;
3461 case PIPE_AUTH_TYPE_NTLMSSP:
3462 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3463 *session_key = data_blob_talloc(mem_ctx,
3464 cli->auth->a_u.ntlmssp_state->session_key.data,
3465 cli->auth->a_u.ntlmssp_state->session_key.length);
3466 break;
3467 case PIPE_AUTH_TYPE_KRB5:
3468 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3469 *session_key = data_blob_talloc(mem_ctx,
3470 cli->auth->a_u.kerberos_auth->session_key.data,
3471 cli->auth->a_u.kerberos_auth->session_key.length);
3472 break;
3473 case PIPE_AUTH_TYPE_NONE:
3474 default:
3475 return NT_STATUS_NO_USER_SESSION_KEY;
3478 return NT_STATUS_OK;