r10780: Fix typo noticed by Volker.
[Samba/nascimento.git] / source3 / rpc_client / cli_pipe.c
blob2e6f42b0e692890b8b3ff5780f8cfbe6aa0ef0fb
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 2 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, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_CLI
26 extern struct pipe_id_info pipe_names[];
28 /********************************************************************
29 Map internal value to wire value.
30 ********************************************************************/
32 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
34 switch (auth_type) {
36 case PIPE_AUTH_TYPE_NONE:
37 return RPC_ANONYMOUS_AUTH_TYPE;
39 case PIPE_AUTH_TYPE_NTLMSSP:
40 return RPC_NTLMSSP_AUTH_TYPE;
42 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
43 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
44 return RPC_SPNEGO_AUTH_TYPE;
46 case PIPE_AUTH_TYPE_SCHANNEL:
47 return RPC_SCHANNEL_AUTH_TYPE;
49 case PIPE_AUTH_TYPE_KRB5:
50 return RPC_KRB5_AUTH_TYPE;
52 default:
53 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
54 "auth type %u\n",
55 (unsigned int)auth_type ));
56 break;
58 return -1;
61 /********************************************************************
62 Rpc pipe call id.
63 ********************************************************************/
65 static uint32 get_rpc_call_id(void)
67 static uint32 call_id = 0;
68 return ++call_id;
71 /*******************************************************************
72 Use SMBreadX to get rest of one fragment's worth of rpc data.
73 Will expand the current_pdu struct to the correct size.
74 ********************************************************************/
76 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
77 prs_struct *current_pdu,
78 uint32 data_to_read,
79 uint32 *current_pdu_offset)
81 size_t size = (size_t)cli->max_recv_frag;
82 uint32 stream_offset = 0;
83 ssize_t num_read;
84 char *pdata;
85 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
87 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
88 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
91 * Grow the buffer if needed to accommodate the data to be read.
94 if (extra_data_size > 0) {
95 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
96 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
97 return NT_STATUS_NO_MEMORY;
99 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
102 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
104 do {
105 /* read data using SMBreadX */
106 if (size > (size_t)data_to_read) {
107 size = (size_t)data_to_read;
110 num_read = cli_read(cli->cli, cli->fnum, pdata,
111 (off_t)stream_offset, size);
113 DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n",
114 (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read));
117 * A dos error of ERRDOS/ERRmoredata is not an error.
119 if (cli_is_dos_error(cli->cli)) {
120 uint32 ecode;
121 uint8 eclass;
122 cli_dos_error(cli->cli, &eclass, &ecode);
123 if (eclass != ERRDOS && ecode != ERRmoredata) {
124 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n",
125 eclass, (unsigned int)ecode,
126 cli_errstr(cli->cli),
127 cli->pipe_name ));
128 return dos_to_ntstatus(eclass, ecode);
133 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
135 if (cli_is_nt_error(cli->cli)) {
136 if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) {
137 DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n",
138 nt_errstr(cli_nt_error(cli->cli)),
139 cli->pipe_name ));
140 return cli_nt_error(cli->cli);
144 if (num_read == -1) {
145 DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n",
146 cli->pipe_name ));
147 return cli_get_nt_error(cli->cli);
150 data_to_read -= num_read;
151 stream_offset += num_read;
152 pdata += num_read;
154 } while (num_read > 0 && data_to_read > 0);
155 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
158 * Update the current offset into current_pdu by the amount read.
160 *current_pdu_offset += stream_offset;
161 return NT_STATUS_OK;
164 /****************************************************************************
165 Try and get a PDU's worth of data from current_pdu. If not, then read more
166 from the wire.
167 ****************************************************************************/
169 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
171 NTSTATUS ret = NT_STATUS_OK;
172 uint32 current_pdu_len = prs_data_size(current_pdu);
174 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
175 if (current_pdu_len < RPC_HEADER_LEN) {
176 /* rpc_read expands the current_pdu struct as neccessary. */
177 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
178 if (!NT_STATUS_IS_OK(ret)) {
179 return ret;
183 /* This next call sets the endian bit correctly in current_pdu. */
184 /* We will propagate this to rbuf later. */
185 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
186 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
187 return NT_STATUS_BUFFER_TOO_SMALL;
190 /* Ensure we have frag_len bytes of data. */
191 if (current_pdu_len < prhdr->frag_len) {
192 /* rpc_read expands the current_pdu struct as neccessary. */
193 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
194 if (!NT_STATUS_IS_OK(ret)) {
195 return ret;
199 if (current_pdu_len < prhdr->frag_len) {
200 return NT_STATUS_BUFFER_TOO_SMALL;
203 return NT_STATUS_OK;
206 /****************************************************************************
207 NTLMSSP specific sign/seal.
208 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
209 In fact I should probably abstract these into identical pieces of code... JRA.
210 ****************************************************************************/
212 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
213 prs_struct *current_pdu,
214 uint8 *p_ss_padding_len)
216 RPC_HDR_AUTH auth_info;
217 uint32 save_offset = prs_offset(current_pdu);
218 uint32 auth_len = prhdr->auth_len;
219 NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state;
220 unsigned char *data = NULL;
221 size_t data_len;
222 unsigned char *full_packet_data = NULL;
223 size_t full_packet_data_len;
224 DATA_BLOB auth_blob;
225 NTSTATUS status;
227 if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
228 return NT_STATUS_OK;
231 if (!ntlmssp_state) {
232 return NT_STATUS_INVALID_PARAMETER;
235 /* Ensure there's enough data for an authenticated response. */
236 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
237 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
238 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
239 (unsigned int)auth_len ));
240 return NT_STATUS_BUFFER_TOO_SMALL;
244 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
245 * after the RPC header.
246 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
247 * functions as NTLMv2 checks the rpc headers also.
250 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
251 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
253 full_packet_data = prs_data_p(current_pdu);
254 full_packet_data_len = prhdr->frag_len - auth_len;
256 /* Pull the auth header and the following data into a blob. */
257 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
258 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
259 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
260 return NT_STATUS_BUFFER_TOO_SMALL;
263 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
264 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
265 return NT_STATUS_BUFFER_TOO_SMALL;
268 auth_blob.data = prs_data_p(current_pdu) + prs_offset(current_pdu);
269 auth_blob.length = auth_len;
271 switch (cli->auth.auth_level) {
272 case PIPE_AUTH_LEVEL_PRIVACY:
273 /* Data is encrypted. */
274 status = ntlmssp_unseal_packet(ntlmssp_state,
275 data, data_len,
276 full_packet_data,
277 full_packet_data_len,
278 &auth_blob);
279 if (!NT_STATUS_IS_OK(status)) {
280 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
281 "packet from remote machine %s on pipe %s "
282 "fnum 0x%x. Error was %s.\n",
283 cli->cli->desthost,
284 cli->pipe_name,
285 (unsigned int)cli->fnum,
286 nt_errstr(status) ));
287 return status;
289 break;
290 case PIPE_AUTH_LEVEL_INTEGRITY:
291 /* Data is signed. */
292 status = ntlmssp_check_packet(ntlmssp_state,
293 data, data_len,
294 full_packet_data,
295 full_packet_data_len,
296 &auth_blob);
297 if (!NT_STATUS_IS_OK(status)) {
298 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
299 "packet from remote machine %s on pipe %s "
300 "fnum 0x%x. Error was %s.\n",
301 cli->cli->desthost,
302 cli->pipe_name,
303 (unsigned int)cli->fnum,
304 nt_errstr(status) ));
305 return status;
307 break;
308 default:
309 DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n",
310 cli->auth.auth_level ));
311 return NT_STATUS_INVALID_INFO_CLASS;
315 * Return the current pointer to the data offset.
318 if(!prs_set_offset(current_pdu, save_offset)) {
319 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
320 (unsigned int)save_offset ));
321 return NT_STATUS_BUFFER_TOO_SMALL;
325 * Remember the padding length. We must remove it from the real data
326 * stream once the sign/seal is done.
329 *p_ss_padding_len = auth_info.auth_pad_len;
331 return NT_STATUS_OK;
334 /****************************************************************************
335 schannel specific sign/seal.
336 ****************************************************************************/
338 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
339 prs_struct *current_pdu,
340 uint8 *p_ss_padding_len)
342 RPC_HDR_AUTH auth_info;
343 RPC_AUTH_SCHANNEL_CHK schannel_chk;
344 uint32 auth_len = prhdr->auth_len;
345 uint32 save_offset = prs_offset(current_pdu);
346 struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth;
347 uint32 data_len;
349 if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
350 return NT_STATUS_OK;
353 if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
354 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
355 return NT_STATUS_INVALID_PARAMETER;
358 if (!schannel_auth) {
359 return NT_STATUS_INVALID_PARAMETER;
362 /* Ensure there's enough data for an authenticated response. */
363 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
364 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
365 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
366 (unsigned int)auth_len ));
367 return NT_STATUS_INVALID_PARAMETER;
370 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
372 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
373 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
374 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
375 return NT_STATUS_BUFFER_TOO_SMALL;
378 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
379 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
380 return NT_STATUS_BUFFER_TOO_SMALL;
383 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
384 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
385 auth_info.auth_type));
386 return NT_STATUS_BUFFER_TOO_SMALL;
389 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
390 &schannel_chk, current_pdu, 0)) {
391 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
392 return NT_STATUS_BUFFER_TOO_SMALL;
395 if (!schannel_decode(schannel_auth,
396 cli->auth.auth_level,
397 SENDER_IS_ACCEPTOR,
398 &schannel_chk,
399 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
400 data_len)) {
401 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
402 "Connection to remote machine %s "
403 "pipe %s fnum 0x%x.\n",
404 cli->cli->desthost,
405 cli->pipe_name,
406 (unsigned int)cli->fnum ));
407 return NT_STATUS_INVALID_PARAMETER;
410 /* The sequence number gets incremented on both send and receive. */
411 schannel_auth->seq_num++;
414 * Return the current pointer to the data offset.
417 if(!prs_set_offset(current_pdu, save_offset)) {
418 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
419 (unsigned int)save_offset ));
420 return NT_STATUS_BUFFER_TOO_SMALL;
424 * Remember the padding length. We must remove it from the real data
425 * stream once the sign/seal is done.
428 *p_ss_padding_len = auth_info.auth_pad_len;
430 return NT_STATUS_OK;
433 /****************************************************************************
434 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
435 ****************************************************************************/
437 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
438 prs_struct *current_pdu,
439 uint8 *p_ss_padding_len)
441 NTSTATUS ret = NT_STATUS_OK;
443 /* Paranioa checks for auth_len. */
444 if (prhdr->auth_len) {
445 if (prhdr->auth_len > prhdr->frag_len) {
446 return NT_STATUS_INVALID_PARAMETER;
449 if (prhdr->auth_len + RPC_HDR_AUTH_LEN < prhdr->auth_len ||
450 prhdr->auth_len + RPC_HDR_AUTH_LEN < RPC_HDR_AUTH_LEN) {
451 /* Integer wrap attempt. */
452 return NT_STATUS_INVALID_PARAMETER;
457 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
460 switch(cli->auth.auth_type) {
461 case PIPE_AUTH_TYPE_NONE:
462 if (prhdr->auth_len) {
463 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
464 "pipe %s fnum 0x%x - got non-zero auth len %u.\n",
465 cli->cli->desthost,
466 cli->pipe_name,
467 (unsigned int)cli->fnum,
468 (unsigned int)prhdr->auth_len ));
469 return NT_STATUS_INVALID_PARAMETER;
471 break;
473 case PIPE_AUTH_TYPE_NTLMSSP:
474 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
475 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
476 if (!NT_STATUS_IS_OK(ret)) {
477 return ret;
479 break;
481 case PIPE_AUTH_TYPE_SCHANNEL:
482 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
483 if (!NT_STATUS_IS_OK(ret)) {
484 return ret;
486 break;
488 case PIPE_AUTH_TYPE_KRB5:
489 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
490 default:
491 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
492 "pipe %s fnum %x - unknown internal auth type %u.\n",
493 cli->cli->desthost,
494 cli->pipe_name,
495 (unsigned int)cli->fnum,
496 cli->auth.auth_type ));
497 return NT_STATUS_INVALID_INFO_CLASS;
500 return NT_STATUS_OK;
503 /****************************************************************************
504 Do basic authentication checks on an incoming pdu.
505 ****************************************************************************/
507 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
508 prs_struct *current_pdu,
509 uint8 expected_pkt_type,
510 char **ppdata,
511 uint32 *pdata_len,
512 prs_struct *return_data)
515 NTSTATUS ret = NT_STATUS_OK;
516 uint32 current_pdu_len = prs_data_size(current_pdu);
518 if (current_pdu_len != prhdr->frag_len) {
519 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
520 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
521 return NT_STATUS_INVALID_PARAMETER;
525 * Point the return values at the real data including the RPC
526 * header. Just in case the caller wants it.
528 *ppdata = prs_data_p(current_pdu);
529 *pdata_len = current_pdu_len;
531 /* Ensure we have the correct type. */
532 switch (prhdr->pkt_type) {
533 case RPC_ALTCONTRESP:
534 case RPC_BINDACK:
536 /* Alter context and bind ack share the same packet definitions. */
537 break;
540 case RPC_RESPONSE:
542 RPC_HDR_RESP rhdr_resp;
543 uint8 ss_padding_len = 0;
545 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
546 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
547 return NT_STATUS_BUFFER_TOO_SMALL;
550 /* Here's where we deal with incoming sign/seal. */
551 ret = cli_pipe_validate_rpc_response(cli, prhdr,
552 current_pdu, &ss_padding_len);
553 if (!NT_STATUS_IS_OK(ret)) {
554 return ret;
557 /* Point the return values at the NDR data. Remember to remove any ss padding. */
558 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
560 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
561 return NT_STATUS_BUFFER_TOO_SMALL;
564 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
566 /* Remember to remove the auth footer. */
567 if (prhdr->auth_len) {
568 /* We've already done integer wrap tests on auth_len in
569 cli_pipe_validate_rpc_response(). */
570 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
571 return NT_STATUS_BUFFER_TOO_SMALL;
573 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
576 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
577 current_pdu_len, *pdata_len, ss_padding_len ));
580 * If this is the first reply, and the allocation hint is reasonably, try and
581 * set up the return_data parse_struct to the correct size.
584 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
585 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
586 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
587 "too large to allocate\n",
588 (unsigned int)rhdr_resp.alloc_hint ));
589 return NT_STATUS_NO_MEMORY;
593 break;
596 case RPC_BINDNACK:
597 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
598 "pipe %s fnum 0x%x!\n",
599 cli->cli->desthost,
600 cli->pipe_name,
601 (unsigned int)cli->fnum));
602 /* Use this for now... */
603 return NT_STATUS_NETWORK_ACCESS_DENIED;
605 case RPC_FAULT:
607 RPC_HDR_RESP rhdr_resp;
608 RPC_HDR_FAULT fault_resp;
610 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
611 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
612 return NT_STATUS_BUFFER_TOO_SMALL;
615 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
616 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
617 return NT_STATUS_BUFFER_TOO_SMALL;
620 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
621 "pipe %s fnum 0x%x!\n",
622 nt_errstr(fault_resp.status),
623 cli->cli->desthost,
624 cli->pipe_name,
625 (unsigned int)cli->fnum));
626 if (NT_STATUS_IS_OK(fault_resp.status)) {
627 return NT_STATUS_UNSUCCESSFUL;
628 } else {
629 return fault_resp.status;
634 default:
635 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
636 "from remote machine %s pipe %s fnum 0x%x!\n",
637 (unsigned int)prhdr->pkt_type,
638 cli->cli->desthost,
639 cli->pipe_name,
640 (unsigned int)cli->fnum));
641 return NT_STATUS_INVALID_INFO_CLASS;
644 if (prhdr->pkt_type != expected_pkt_type) {
645 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
646 "pipe %s fnum %x got an unexpected RPC packet "
647 "type - %u, not %u\n",
648 cli->cli->desthost,
649 cli->pipe_name,
650 (unsigned int)cli->fnum,
651 prhdr->pkt_type,
652 expected_pkt_type));
653 return NT_STATUS_INVALID_INFO_CLASS;
656 /* Do this just before return - we don't want to modify any rpc header
657 data before now as we may have needed to do cryptographic actions on
658 it before. */
660 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
661 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
662 "setting fragment first/last ON.\n"));
663 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
666 return NT_STATUS_OK;
669 /****************************************************************************
670 Ensure we eat the just processed pdu from the current_pdu prs_struct.
671 Normally the frag_len and buffer size will match, but on the first trans
672 reply there is a theoretical chance that buffer size > frag_len, so we must
673 deal with that.
674 ****************************************************************************/
676 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
678 uint32 current_pdu_len = prs_data_size(current_pdu);
680 if (current_pdu_len < prhdr->frag_len) {
681 return NT_STATUS_BUFFER_TOO_SMALL;
684 /* Common case. */
685 if (current_pdu_len == (uint32)prhdr->frag_len) {
686 prs_mem_free(current_pdu);
687 prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL);
688 /* Make current_pdu dynamic with no memory. */
689 prs_give_memory(current_pdu, 0, 0, True);
690 return NT_STATUS_OK;
694 * Oh no ! More data in buffer than we processed in current pdu.
695 * Cheat. Move the data down and shrink the buffer.
698 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
699 current_pdu_len - prhdr->frag_len);
701 /* Remember to set the read offset back to zero. */
702 prs_set_offset(current_pdu, 0);
704 /* Shrink the buffer. */
705 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
706 return NT_STATUS_BUFFER_TOO_SMALL;
709 return NT_STATUS_OK;
712 /****************************************************************************
713 Send data on an rpc pipe via trans. The prs_struct data must be the last
714 pdu fragment of an NDR data stream.
716 Receive response data from an rpc pipe, which may be large...
718 Read the first fragment: unfortunately have to use SMBtrans for the first
719 bit, then SMBreadX for subsequent bits.
721 If first fragment received also wasn't the last fragment, continue
722 getting fragments until we _do_ receive the last fragment.
724 Request/Response PDU's look like the following...
726 |<------------------PDU len----------------------------------------------->|
727 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
729 +------------+-----------------+-------------+---------------+-------------+
730 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
731 +------------+-----------------+-------------+---------------+-------------+
733 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
734 signing & sealing being negotiated.
736 ****************************************************************************/
738 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
739 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
740 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
741 uint8 expected_pkt_type)
743 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
744 char *rparam = NULL;
745 uint32 rparam_len = 0;
746 uint16 setup[2];
747 char *pdata = data ? prs_data_p(data) : NULL;
748 uint32 data_len = data ? prs_offset(data) : 0;
749 char *prdata = NULL;
750 uint32 rdata_len = 0;
751 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
752 uint32 current_rbuf_offset = 0;
753 prs_struct current_pdu;
755 #ifdef DEVELOPER
756 /* Ensure we're not sending too much. */
757 SMB_ASSERT(data_len <= max_data);
758 #endif
760 /* Set up the current pdu parse struct. */
761 prs_init(&current_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL);
763 /* Create setup parameters - must be in native byte order. */
764 setup[0] = TRANSACT_DCERPCCMD;
765 setup[1] = cli->fnum; /* Pipe file handle. */
767 DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
768 cli->cli->desthost,
769 cli->pipe_name,
770 (unsigned int)cli->fnum ));
773 * Send the last (or only) fragment of an RPC request. For small
774 * amounts of data (about 1024 bytes or so) the RPC request and response
775 * appears in a SMBtrans request and response.
778 if (!cli_api_pipe(cli->cli, "\\PIPE\\",
779 setup, 2, 0, /* Setup, length, max */
780 NULL, 0, 0, /* Params, length, max */
781 pdata, data_len, max_data, /* data, length, max */
782 &rparam, &rparam_len, /* return params, len */
783 &prdata, &rdata_len)) /* return data, len */
785 DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x"
786 "returned critical error. Error was %s\n",
787 cli->cli->desthost,
788 cli->pipe_name,
789 (unsigned int)cli->fnum,
790 cli_errstr(cli->cli)));
791 ret = cli_get_nt_error(cli->cli);
792 goto err;
795 /* Throw away returned params - we know we won't use them. */
797 SAFE_FREE(rparam);
799 if (prdata == NULL) {
800 DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
801 "fnum 0x%x failed to return data.\n",
802 cli->cli->desthost,
803 cli->pipe_name,
804 (unsigned int)cli->fnum));
805 /* Yes - some calls can truely return no data... */
806 prs_mem_free(&current_pdu);
807 return NT_STATUS_OK;
811 * Give this memory as dynamic to the current pdu.
814 prs_give_memory(&current_pdu, prdata, rdata_len, True);
816 /* Ensure we can mess with the return prs_struct. */
817 SMB_ASSERT(UNMARSHALLING(rbuf));
818 SMB_ASSERT(prs_data_size(rbuf) == 0);
820 /* Make rbuf dynamic with no memory. */
821 prs_give_memory(rbuf, 0, 0, True);
823 while(1) {
824 RPC_HDR rhdr;
825 char *ret_data;
826 uint32 ret_data_len;
828 /* Ensure we have enough data for a pdu. */
829 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
830 if (!NT_STATUS_IS_OK(ret)) {
831 goto err;
834 /* We pass in rbuf here so if the alloc hint is set correctly
835 we can set the output size and avoid reallocs. */
837 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
838 &ret_data, &ret_data_len, rbuf);
840 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
841 prs_data_size(&current_pdu), current_rbuf_offset ));
843 if (!NT_STATUS_IS_OK(ret)) {
844 goto err;
847 if ((rhdr.flags & RPC_FLG_FIRST)) {
848 if (rhdr.pack_type[0] == 0) {
849 /* Set the data type correctly for big-endian data on the first packet. */
850 DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
851 "PDU data format is big-endian.\n",
852 cli->cli->desthost,
853 cli->pipe_name,
854 (unsigned int)cli->fnum));
856 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
857 } else {
858 /* Check endianness on subsequent packets. */
859 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
860 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
861 rbuf->bigendian_data ? "big" : "little",
862 current_pdu.bigendian_data ? "big" : "little" ));
863 ret = NT_STATUS_INVALID_PARAMETER;
864 goto err;
869 /* Now copy the data portion out of the pdu into rbuf. */
870 if (!prs_force_grow(rbuf, ret_data_len)) {
871 ret = NT_STATUS_NO_MEMORY;
872 goto err;
874 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
875 current_rbuf_offset += ret_data_len;
877 /* See if we've finished with all the data in current_pdu yet ? */
878 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
879 if (!NT_STATUS_IS_OK(ret)) {
880 goto err;
883 if (rhdr.flags & RPC_FLG_LAST) {
884 break; /* We're done. */
888 DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
889 cli->cli->desthost,
890 cli->pipe_name,
891 (unsigned int)cli->fnum,
892 (unsigned int)prs_data_size(rbuf) ));
894 prs_mem_free(&current_pdu);
895 return NT_STATUS_OK;
897 err:
899 prs_mem_free(&current_pdu);
900 prs_mem_free(rbuf);
901 return ret;
904 /*******************************************************************
905 Creates krb5 auth bind.
906 ********************************************************************/
908 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
909 enum pipe_auth_level auth_level,
910 RPC_HDR_AUTH *pauth_out,
911 prs_struct *auth_data)
913 #ifdef HAVE_KRB5
914 int ret;
915 struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
916 DATA_BLOB tkt = data_blob(NULL, 0);
917 DATA_BLOB tkt_wrapped = data_blob(NULL, 0);
919 /* We may change the pad length before marshalling. */
920 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
922 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
923 a->service_principal ));
925 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
927 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
928 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED);
930 if (ret) {
931 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
932 "failed with %s\n",
933 a->service_principal,
934 error_message(ret) ));
936 data_blob_free(&tkt);
937 prs_mem_free(auth_data);
938 return NT_STATUS_INVALID_PARAMETER;
941 /* wrap that up in a nice GSS-API wrapping */
942 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
944 data_blob_free(&tkt);
946 /* Auth len in the rpc header doesn't include auth_header. */
947 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
948 data_blob_free(&tkt_wrapped);
949 prs_mem_free(auth_data);
950 return NT_STATUS_NO_MEMORY;
953 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
954 dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length);
956 data_blob_free(&tkt_wrapped);
957 return NT_STATUS_OK;
958 #else
959 return NT_STATUS_INVALID_PARAMETER;
960 #endif
963 /*******************************************************************
964 Creates SPNEGO NTLMSSP auth bind.
965 ********************************************************************/
967 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
968 enum pipe_auth_level auth_level,
969 RPC_HDR_AUTH *pauth_out,
970 prs_struct *auth_data)
972 NTSTATUS nt_status;
973 DATA_BLOB null_blob = data_blob(NULL, 0);
974 DATA_BLOB request = data_blob(NULL, 0);
975 DATA_BLOB spnego_msg = data_blob(NULL, 0);
977 /* We may change the pad length before marshalling. */
978 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
980 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
981 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
982 null_blob,
983 &request);
985 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
986 data_blob_free(&request);
987 prs_mem_free(auth_data);
988 return nt_status;
991 /* Wrap this in SPNEGO. */
992 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
994 data_blob_free(&request);
996 /* Auth len in the rpc header doesn't include auth_header. */
997 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
998 data_blob_free(&spnego_msg);
999 prs_mem_free(auth_data);
1000 return NT_STATUS_NO_MEMORY;
1003 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1004 dump_data(5, (const char *)spnego_msg.data, spnego_msg.length);
1006 data_blob_free(&spnego_msg);
1007 return NT_STATUS_OK;
1010 /*******************************************************************
1011 Creates NTLMSSP auth bind.
1012 ********************************************************************/
1014 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1015 enum pipe_auth_level auth_level,
1016 RPC_HDR_AUTH *pauth_out,
1017 prs_struct *auth_data)
1019 NTSTATUS nt_status;
1020 DATA_BLOB null_blob = data_blob(NULL, 0);
1021 DATA_BLOB request = data_blob(NULL, 0);
1023 /* We may change the pad length before marshalling. */
1024 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1026 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1027 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1028 null_blob,
1029 &request);
1031 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1032 data_blob_free(&request);
1033 prs_mem_free(auth_data);
1034 return nt_status;
1037 /* Auth len in the rpc header doesn't include auth_header. */
1038 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1039 data_blob_free(&request);
1040 prs_mem_free(auth_data);
1041 return NT_STATUS_NO_MEMORY;
1044 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1045 dump_data(5, (const char *)request.data, request.length);
1047 data_blob_free(&request);
1048 return NT_STATUS_OK;
1051 /*******************************************************************
1052 Creates schannel auth bind.
1053 ********************************************************************/
1055 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1056 enum pipe_auth_level auth_level,
1057 RPC_HDR_AUTH *pauth_out,
1058 prs_struct *auth_data)
1060 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1062 /* We may change the pad length before marshalling. */
1063 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1065 /* Use lp_workgroup() if domain not specified */
1067 if (!cli->domain || !cli->domain[0]) {
1068 cli->domain = lp_workgroup();
1071 init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
1074 * Now marshall the data into the auth parse_struct.
1077 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1078 &schannel_neg, auth_data, 0)) {
1079 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1080 prs_mem_free(auth_data);
1081 return NT_STATUS_NO_MEMORY;
1084 return NT_STATUS_OK;
1087 /*******************************************************************
1088 Creates the internals of a DCE/RPC bind request or alter context PDU.
1089 ********************************************************************/
1091 static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type,
1092 prs_struct *rpc_out,
1093 uint32 rpc_call_id,
1094 RPC_IFACE *abstract,
1095 RPC_IFACE *transfer,
1096 RPC_HDR_AUTH *phdr_auth,
1097 prs_struct *pauth_info)
1099 RPC_HDR hdr;
1100 RPC_HDR_RB hdr_rb;
1101 RPC_CONTEXT rpc_ctx;
1102 uint16 auth_len = prs_offset(pauth_info);
1103 uint8 ss_padding_len = 0;
1104 uint16 frag_len = 0;
1106 /* create the RPC context. */
1107 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1109 /* create the bind request RPC_HDR_RB */
1110 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1112 /* Start building the frag length. */
1113 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1115 /* Do we need to pad ? */
1116 if (auth_len) {
1117 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1118 if (data_len % 8) {
1119 ss_padding_len = 8 - (data_len % 8);
1120 phdr_auth->auth_pad_len = ss_padding_len;
1122 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1125 /* Create the request RPC_HDR */
1126 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1128 /* Marshall the RPC header */
1129 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1130 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1131 return NT_STATUS_NO_MEMORY;
1134 /* Marshall the bind request data */
1135 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1136 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1137 return NT_STATUS_NO_MEMORY;
1141 * Grow the outgoing buffer to store any auth info.
1144 if(auth_len != 0) {
1145 if (ss_padding_len) {
1146 unsigned char pad[8];
1147 memset(pad, '\0', 8);
1148 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1149 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1150 return NT_STATUS_NO_MEMORY;
1154 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1155 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1156 return NT_STATUS_NO_MEMORY;
1160 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1161 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1162 return NT_STATUS_NO_MEMORY;
1166 return NT_STATUS_OK;
1169 /*******************************************************************
1170 Creates a DCE/RPC bind request.
1171 ********************************************************************/
1173 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1174 prs_struct *rpc_out,
1175 uint32 rpc_call_id,
1176 RPC_IFACE *abstract, RPC_IFACE *transfer,
1177 enum pipe_auth_type auth_type,
1178 enum pipe_auth_level auth_level)
1180 RPC_HDR_AUTH hdr_auth;
1181 prs_struct auth_info;
1182 NTSTATUS ret = NT_STATUS_OK;
1184 ZERO_STRUCT(hdr_auth);
1185 prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
1187 switch (auth_type) {
1188 case PIPE_AUTH_TYPE_SCHANNEL:
1189 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1190 if (!NT_STATUS_IS_OK(ret)) {
1191 prs_mem_free(&auth_info);
1192 return ret;
1194 break;
1196 case PIPE_AUTH_TYPE_NTLMSSP:
1197 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1198 if (!NT_STATUS_IS_OK(ret)) {
1199 prs_mem_free(&auth_info);
1200 return ret;
1202 break;
1204 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1205 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1206 if (!NT_STATUS_IS_OK(ret)) {
1207 prs_mem_free(&auth_info);
1208 return ret;
1210 break;
1212 case PIPE_AUTH_TYPE_KRB5:
1213 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1214 if (!NT_STATUS_IS_OK(ret)) {
1215 prs_mem_free(&auth_info);
1216 return ret;
1218 break;
1220 case PIPE_AUTH_TYPE_NONE:
1221 break;
1223 default:
1224 /* "Can't" happen. */
1225 return NT_STATUS_INVALID_INFO_CLASS;
1228 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1229 rpc_out,
1230 rpc_call_id,
1231 abstract,
1232 transfer,
1233 &hdr_auth,
1234 &auth_info);
1236 prs_mem_free(&auth_info);
1237 return ret;
1240 /*******************************************************************
1241 Create and add the NTLMSSP sign/seal auth header and data.
1242 ********************************************************************/
1244 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1245 RPC_HDR *phdr,
1246 uint32 ss_padding_len,
1247 prs_struct *outgoing_pdu)
1249 RPC_HDR_AUTH auth_info;
1250 NTSTATUS status;
1251 DATA_BLOB auth_blob = data_blob(NULL, 0);
1252 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1254 if (!cli->auth.a_u.ntlmssp_state) {
1255 return NT_STATUS_INVALID_PARAMETER;
1258 /* Init and marshall the auth header. */
1259 init_rpc_hdr_auth(&auth_info,
1260 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1261 cli->auth.auth_level,
1262 ss_padding_len,
1263 1 /* context id. */);
1265 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1266 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1267 data_blob_free(&auth_blob);
1268 return NT_STATUS_NO_MEMORY;
1271 switch (cli->auth.auth_level) {
1272 case PIPE_AUTH_LEVEL_PRIVACY:
1273 /* Data portion is encrypted. */
1274 status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
1275 prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1276 data_and_pad_len,
1277 prs_data_p(outgoing_pdu),
1278 (size_t)prs_offset(outgoing_pdu),
1279 &auth_blob);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 data_blob_free(&auth_blob);
1282 return status;
1284 break;
1286 case PIPE_AUTH_LEVEL_INTEGRITY:
1287 /* Data is signed. */
1288 status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
1289 prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1290 data_and_pad_len,
1291 prs_data_p(outgoing_pdu),
1292 (size_t)prs_offset(outgoing_pdu),
1293 &auth_blob);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 data_blob_free(&auth_blob);
1296 return status;
1298 break;
1300 default:
1301 /* Can't happen. */
1302 smb_panic("bad auth level");
1303 /* Notreached. */
1304 return NT_STATUS_INVALID_PARAMETER;
1307 /* Finally marshall the blob. */
1309 if (!prs_copy_data_in(outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) {
1310 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1311 (unsigned int)NTLMSSP_SIG_SIZE));
1312 data_blob_free(&auth_blob);
1313 return NT_STATUS_NO_MEMORY;
1316 data_blob_free(&auth_blob);
1317 return NT_STATUS_OK;
1320 /*******************************************************************
1321 Create and add the schannel sign/seal auth header and data.
1322 ********************************************************************/
1324 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1325 RPC_HDR *phdr,
1326 uint32 ss_padding_len,
1327 prs_struct *outgoing_pdu)
1329 RPC_HDR_AUTH auth_info;
1330 RPC_AUTH_SCHANNEL_CHK verf;
1331 struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
1332 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1333 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1335 if (!sas) {
1336 return NT_STATUS_INVALID_PARAMETER;
1339 /* Init and marshall the auth header. */
1340 init_rpc_hdr_auth(&auth_info,
1341 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1342 cli->auth.auth_level,
1343 ss_padding_len,
1344 1 /* context id. */);
1346 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1347 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1348 return NT_STATUS_NO_MEMORY;
1351 switch (cli->auth.auth_level) {
1352 case PIPE_AUTH_LEVEL_PRIVACY:
1353 case PIPE_AUTH_LEVEL_INTEGRITY:
1354 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1355 sas->seq_num));
1357 schannel_encode(sas,
1358 cli->auth.auth_level,
1359 SENDER_IS_INITIATOR,
1360 &verf,
1361 data_p,
1362 data_and_pad_len);
1364 sas->seq_num++;
1365 break;
1367 default:
1368 /* Can't happen. */
1369 smb_panic("bad auth level");
1370 /* Notreached. */
1371 return NT_STATUS_INVALID_PARAMETER;
1374 /* Finally marshall the blob. */
1375 smb_io_rpc_auth_schannel_chk("",
1376 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1377 &verf,
1378 outgoing_pdu,
1381 return NT_STATUS_OK;
1384 /*******************************************************************
1385 Calculate how much data we're going to send in this packet, also
1386 work out any sign/seal padding length.
1387 ********************************************************************/
1389 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1390 uint32 data_left,
1391 uint16 *p_frag_len,
1392 uint16 *p_auth_len,
1393 uint32 *p_ss_padding)
1395 uint32 data_space, data_len;
1397 switch (cli->auth.auth_level) {
1398 case PIPE_AUTH_LEVEL_NONE:
1399 case PIPE_AUTH_LEVEL_CONNECT:
1400 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1401 data_len = MIN(data_space, data_left);
1402 *p_ss_padding = 0;
1403 *p_auth_len = 0;
1404 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1405 return data_len;
1407 case PIPE_AUTH_LEVEL_INTEGRITY:
1408 case PIPE_AUTH_LEVEL_PRIVACY:
1409 /* Treat the same for all authenticated rpc requests. */
1410 switch(cli->auth.auth_type) {
1411 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1412 case PIPE_AUTH_TYPE_NTLMSSP:
1413 *p_auth_len = NTLMSSP_SIG_SIZE;
1414 break;
1415 case PIPE_AUTH_TYPE_SCHANNEL:
1416 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1417 break;
1418 default:
1419 smb_panic("bad auth type");
1420 break;
1423 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1424 RPC_HDR_AUTH_LEN - *p_auth_len;
1426 data_len = MIN(data_space, data_left);
1427 if (data_len % 8) {
1428 *p_ss_padding = 8 - (data_len % 8);
1430 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1431 data_len + *p_ss_padding + /* data plus padding. */
1432 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1433 return data_len;
1435 default:
1436 smb_panic("bad auth level");
1437 /* Notreached. */
1438 return 0;
1442 /*******************************************************************
1443 External interface.
1444 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1445 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1446 and deals with signing/sealing details.
1447 ********************************************************************/
1449 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1450 uint8 op_num,
1451 prs_struct *in_data,
1452 prs_struct *out_data)
1454 NTSTATUS ret;
1455 uint32 data_left = prs_offset(in_data);
1456 uint32 alloc_hint = prs_offset(in_data);
1457 uint32 data_sent_thistime = 0;
1458 uint32 current_data_offset = 0;
1459 uint32 call_id = get_rpc_call_id();
1460 char pad[8];
1461 prs_struct outgoing_pdu;
1463 memset(pad, '\0', 8);
1465 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1466 /* Server is screwed up ! */
1467 return NT_STATUS_INVALID_PARAMETER;
1470 prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);
1472 while (1) {
1473 RPC_HDR hdr;
1474 RPC_HDR_REQ hdr_req;
1475 uint16 auth_len = 0;
1476 uint16 frag_len = 0;
1477 uint8 flags = 0;
1478 uint32 ss_padding = 0;
1480 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1481 &frag_len, &auth_len, &ss_padding);
1483 if (current_data_offset == 0) {
1484 flags = RPC_FLG_FIRST;
1487 if (data_sent_thistime == data_left) {
1488 flags |= RPC_FLG_LAST;
1491 /* Create and marshall the header and request header. */
1492 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1494 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1495 prs_mem_free(&outgoing_pdu);
1496 return NT_STATUS_NO_MEMORY;
1499 /* Create the rpc request RPC_HDR_REQ */
1500 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1502 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1503 prs_mem_free(&outgoing_pdu);
1504 return NT_STATUS_NO_MEMORY;
1507 /* Copy in the data, plus any ss padding. */
1508 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1509 prs_mem_free(&outgoing_pdu);
1510 return NT_STATUS_NO_MEMORY;
1513 /* Copy the sign/seal padding data. */
1514 if (ss_padding) {
1515 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1516 prs_mem_free(&outgoing_pdu);
1517 return NT_STATUS_NO_MEMORY;
1521 /* Generate any auth sign/seal and add the auth footer. */
1522 if (auth_len) {
1523 switch (cli->auth.auth_type) {
1524 case PIPE_AUTH_TYPE_NONE:
1525 break;
1526 case PIPE_AUTH_TYPE_NTLMSSP:
1527 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1528 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1529 if (!NT_STATUS_IS_OK(ret)) {
1530 prs_mem_free(&outgoing_pdu);
1531 return ret;
1533 break;
1534 case PIPE_AUTH_TYPE_SCHANNEL:
1535 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1536 if (!NT_STATUS_IS_OK(ret)) {
1537 prs_mem_free(&outgoing_pdu);
1538 return ret;
1540 break;
1541 default:
1542 smb_panic("bad auth type");
1543 break; /* notreached */
1547 /* Actually send the packet. */
1548 if (flags & RPC_FLG_LAST) {
1549 /* Last packet - send the data, get the reply and return. */
1550 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1551 prs_mem_free(&outgoing_pdu);
1554 if (DEBUGLEVEL >= 50) {
1555 pstring dump_name;
1556 /* Also capture received data */
1557 slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d",
1558 dyn_LOGFILEBASE, cli->pipe_name, op_num);
1559 prs_dump(dump_name, op_num, out_data);
1562 return ret;
1563 } else {
1564 /* More packets to come - write and continue. */
1565 ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
1566 prs_data_p(&outgoing_pdu),
1567 (off_t)0,
1568 (size_t)hdr.frag_len);
1570 if (num_written != hdr.frag_len) {
1571 prs_mem_free(&outgoing_pdu);
1572 return cli_get_nt_error(cli->cli);
1576 current_data_offset += data_sent_thistime;
1577 data_left -= data_sent_thistime;
1579 /* Reset the marshalling position back to zero. */
1580 if (!prs_set_offset(&outgoing_pdu, 0)) {
1581 prs_mem_free(&outgoing_pdu);
1582 return NT_STATUS_NO_MEMORY;
1586 #if 0
1587 /****************************************************************************
1588 Set the handle state.
1589 ****************************************************************************/
1591 static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1592 const char *pipe_name, uint16 device_state)
1594 BOOL state_set = False;
1595 char param[2];
1596 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1597 char *rparam = NULL;
1598 char *rdata = NULL;
1599 uint32 rparam_len, rdata_len;
1601 if (pipe_name == NULL)
1602 return False;
1604 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1605 cli->fnum, pipe_name, device_state));
1607 /* create parameters: device state */
1608 SSVAL(param, 0, device_state);
1610 /* create setup parameters. */
1611 setup[0] = 0x0001;
1612 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1614 /* send the data on \PIPE\ */
1615 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1616 setup, 2, 0, /* setup, length, max */
1617 param, 2, 0, /* param, length, max */
1618 NULL, 0, 1024, /* data, length, max */
1619 &rparam, &rparam_len, /* return param, length */
1620 &rdata, &rdata_len)) /* return data, length */
1622 DEBUG(5, ("Set Handle state: return OK\n"));
1623 state_set = True;
1626 SAFE_FREE(rparam);
1627 SAFE_FREE(rdata);
1629 return state_set;
1631 #endif
1633 /****************************************************************************
1634 Check the rpc bind acknowledge response.
1635 ****************************************************************************/
1637 static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer)
1639 if ( pipe_idx >= PI_MAX_PIPES ) {
1640 DEBUG(0,("valid_pipe_name: Programmer error! Invalid pipe index [%d]\n",
1641 pipe_idx));
1642 return False;
1645 DEBUG(5,("Bind Abstract Syntax: "));
1646 dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax,
1647 sizeof(pipe_names[pipe_idx].abstr_syntax));
1648 DEBUG(5,("Bind Transfer Syntax: "));
1649 dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax,
1650 sizeof(pipe_names[pipe_idx].trans_syntax));
1652 /* copy the required syntaxes out so we can do the right bind */
1654 *transfer = pipe_names[pipe_idx].trans_syntax;
1655 *abstract = pipe_names[pipe_idx].abstr_syntax;
1657 return True;
1660 /****************************************************************************
1661 Check the rpc bind acknowledge response.
1662 ****************************************************************************/
1664 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
1666 if ( hdr_ba->addr.len == 0) {
1667 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1670 # if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
1671 if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
1672 !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
1674 DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n",
1675 pipe_names[i].server_pipe ,hdr_ba->addr.str));
1676 return False;
1679 DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe ));
1681 if (pipe_names[pipe_idx].server_pipe == NULL) {
1682 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
1683 return False;
1685 #endif /* JERRY */
1687 /* check the transfer syntax */
1688 if ((hdr_ba->transfer.version != transfer->version) ||
1689 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1690 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1691 return False;
1694 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1695 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1696 hdr_ba->res.num_results, hdr_ba->res.reason));
1699 DEBUG(5,("check_bind_response: accepted!\n"));
1700 return True;
1703 /*******************************************************************
1704 Creates a DCE/RPC bind authentication response.
1705 This is the packet that is sent back to the server once we
1706 have received a BIND-ACK, to finish the third leg of
1707 the authentication handshake.
1708 ********************************************************************/
1710 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1711 uint32 rpc_call_id,
1712 enum pipe_auth_type auth_type,
1713 enum pipe_auth_level auth_level,
1714 DATA_BLOB *pauth_blob,
1715 prs_struct *rpc_out)
1717 RPC_HDR hdr;
1718 RPC_HDR_AUTH hdr_auth;
1719 uint32 pad = 0;
1721 /* Create the request RPC_HDR */
1722 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1723 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1724 pauth_blob->length );
1726 /* Marshall it. */
1727 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1728 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1729 return NT_STATUS_NO_MEMORY;
1733 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1734 about padding - shouldn't this pad to length 8 ? JRA.
1737 /* 4 bytes padding. */
1738 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1739 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1740 return NT_STATUS_NO_MEMORY;
1743 /* Create the request RPC_HDR_AUTHA */
1744 init_rpc_hdr_auth(&hdr_auth,
1745 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1746 auth_level, 0, 1);
1748 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1749 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1750 return NT_STATUS_NO_MEMORY;
1754 * Append the auth data to the outgoing buffer.
1757 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1758 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1759 return NT_STATUS_NO_MEMORY;
1762 return NT_STATUS_OK;
1765 /****************************************************************************
1766 Create and send the third packet in an RPC auth.
1767 ****************************************************************************/
1769 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1770 RPC_HDR *phdr,
1771 prs_struct *rbuf,
1772 uint32 rpc_call_id,
1773 enum pipe_auth_type auth_type,
1774 enum pipe_auth_level auth_level)
1776 DATA_BLOB server_response = data_blob(NULL,0);
1777 DATA_BLOB client_reply = data_blob(NULL,0);
1778 RPC_HDR_AUTH hdr_auth;
1779 NTSTATUS nt_status;
1780 prs_struct rpc_out;
1781 ssize_t ret;
1783 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1784 return NT_STATUS_INVALID_PARAMETER;
1787 /* Process the returned NTLMSSP blob first. */
1788 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1789 return NT_STATUS_INVALID_PARAMETER;
1792 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1793 return NT_STATUS_INVALID_PARAMETER;
1796 /* TODO - check auth_type/auth_level match. */
1798 server_response = data_blob(NULL, phdr->auth_len);
1799 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1801 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1802 server_response,
1803 &client_reply);
1805 if (!NT_STATUS_IS_OK(nt_status)) {
1806 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1807 return nt_status;
1810 prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
1812 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1813 auth_type, auth_level,
1814 &client_reply, &rpc_out);
1816 if (!NT_STATUS_IS_OK(nt_status)) {
1817 prs_mem_free(&rpc_out);
1818 data_blob_free(&client_reply);
1819 data_blob_free(&server_response);
1820 return nt_status;
1823 /* 8 here is named pipe message mode. */
1824 ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
1825 (size_t)prs_offset(&rpc_out));
1827 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1828 DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
1829 prs_mem_free(&rpc_out);
1830 data_blob_free(&client_reply);
1831 data_blob_free(&server_response);
1832 return cli_get_nt_error(cli->cli);
1835 DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
1836 "fnum 0x%x sent auth3 response ok.\n",
1837 cli->cli->desthost,
1838 cli->pipe_name,
1839 (unsigned int)cli->fnum));
1841 prs_mem_free(&rpc_out);
1842 data_blob_free(&client_reply);
1843 data_blob_free(&server_response);
1844 return NT_STATUS_OK;
1847 /*******************************************************************
1848 Creates a DCE/RPC bind alter context authentication request which
1849 may contain a spnego auth blobl
1850 ********************************************************************/
1852 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
1853 RPC_IFACE *abstract,
1854 RPC_IFACE *transfer,
1855 enum pipe_auth_level auth_level,
1856 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1857 prs_struct *rpc_out)
1859 RPC_HDR_AUTH hdr_auth;
1860 prs_struct auth_info;
1861 NTSTATUS ret = NT_STATUS_OK;
1863 ZERO_STRUCT(hdr_auth);
1864 prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
1866 /* We may change the pad length before marshalling. */
1867 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1869 if (pauth_blob->length) {
1870 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
1871 prs_mem_free(&auth_info);
1872 return NT_STATUS_NO_MEMORY;
1876 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
1877 rpc_out,
1878 rpc_call_id,
1879 abstract,
1880 transfer,
1881 &hdr_auth,
1882 &auth_info);
1883 prs_mem_free(&auth_info);
1884 return ret;
1887 /*******************************************************************
1888 Third leg of the SPNEGO bind mechanism - sends alter context PDU
1889 and gets a response.
1890 ********************************************************************/
1892 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
1893 RPC_HDR *phdr,
1894 prs_struct *rbuf,
1895 uint32 rpc_call_id,
1896 RPC_IFACE *abstract,
1897 RPC_IFACE *transfer,
1898 enum pipe_auth_type auth_type,
1899 enum pipe_auth_level auth_level)
1901 DATA_BLOB server_spnego_response = data_blob(NULL,0);
1902 DATA_BLOB server_ntlm_response = data_blob(NULL,0);
1903 DATA_BLOB client_reply = data_blob(NULL,0);
1904 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1905 RPC_HDR_AUTH hdr_auth;
1906 NTSTATUS nt_status;
1907 prs_struct rpc_out;
1909 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1910 return NT_STATUS_INVALID_PARAMETER;
1913 /* Process the returned NTLMSSP blob first. */
1914 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1915 return NT_STATUS_INVALID_PARAMETER;
1918 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1919 return NT_STATUS_INVALID_PARAMETER;
1922 server_spnego_response = data_blob(NULL, phdr->auth_len);
1923 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1925 /* The server might give us back two challenges - tmp_blob is for the second. */
1926 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
1927 data_blob_free(&server_spnego_response);
1928 data_blob_free(&server_ntlm_response);
1929 data_blob_free(&tmp_blob);
1930 return NT_STATUS_INVALID_PARAMETER;
1933 /* We're finished with the server spnego response and the tmp_blob. */
1934 data_blob_free(&server_spnego_response);
1935 data_blob_free(&tmp_blob);
1937 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1938 server_ntlm_response,
1939 &client_reply);
1941 /* Finished with the server_ntlm response */
1942 data_blob_free(&server_ntlm_response);
1944 if (!NT_STATUS_IS_OK(nt_status)) {
1945 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
1946 data_blob_free(&client_reply);
1947 return nt_status;
1950 /* SPNEGO wrap the client reply. */
1951 tmp_blob = spnego_gen_auth(client_reply);
1952 data_blob_free(&client_reply);
1953 client_reply = tmp_blob;
1954 tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */
1956 /* Now prepare the alter context pdu. */
1957 prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
1959 nt_status = create_rpc_alter_context(rpc_call_id,
1960 abstract,
1961 transfer,
1962 auth_level,
1963 &client_reply,
1964 &rpc_out);
1966 data_blob_free(&client_reply);
1968 if (!NT_STATUS_IS_OK(nt_status)) {
1969 prs_mem_free(&rpc_out);
1970 return nt_status;
1973 /* Initialize the returning data struct. */
1974 prs_mem_free(rbuf);
1975 prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
1977 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
1978 if (!NT_STATUS_IS_OK(nt_status)) {
1979 prs_mem_free(&rpc_out);
1980 return nt_status;
1983 prs_mem_free(&rpc_out);
1985 /* Get the auth blob from the reply. */
1986 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
1987 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
1988 return NT_STATUS_BUFFER_TOO_SMALL;
1991 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1992 return NT_STATUS_INVALID_PARAMETER;
1995 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1996 return NT_STATUS_INVALID_PARAMETER;
1999 server_spnego_response = data_blob(NULL, phdr->auth_len);
2000 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2002 /* Check we got a valid auth response. */
2003 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) {
2004 data_blob_free(&server_spnego_response);
2005 data_blob_free(&tmp_blob);
2006 return NT_STATUS_INVALID_PARAMETER;
2009 data_blob_free(&server_spnego_response);
2010 data_blob_free(&tmp_blob);
2012 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2013 "remote machine %s pipe %s fnum 0x%x.\n",
2014 cli->cli->desthost,
2015 cli->pipe_name,
2016 (unsigned int)cli->fnum));
2018 return NT_STATUS_OK;
2021 /****************************************************************************
2022 Do an rpc bind.
2023 ****************************************************************************/
2025 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2026 enum pipe_auth_type auth_type,
2027 enum pipe_auth_level auth_level)
2029 RPC_HDR hdr;
2030 RPC_HDR_BA hdr_ba;
2031 RPC_IFACE abstract;
2032 RPC_IFACE transfer;
2033 prs_struct rpc_out;
2034 prs_struct rbuf;
2035 uint32 rpc_call_id;
2036 NTSTATUS status;
2038 DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
2039 (unsigned int)cli->fnum,
2040 cli->pipe_name,
2041 (unsigned int)auth_type,
2042 (unsigned int)auth_level ));
2044 if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {
2045 return NT_STATUS_INVALID_PARAMETER;
2048 prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);
2050 rpc_call_id = get_rpc_call_id();
2052 /* Marshall the outgoing data. */
2053 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2054 &abstract, &transfer,
2055 auth_type,
2056 auth_level);
2058 if (!NT_STATUS_IS_OK(status)) {
2059 prs_mem_free(&rpc_out);
2060 return status;
2063 /* Initialize the incoming data struct. */
2064 prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
2066 /* send data on \PIPE\. receive a response */
2067 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 prs_mem_free(&rpc_out);
2070 return status;
2073 prs_mem_free(&rpc_out);
2075 DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
2076 "fnum 0x%x bind request returned ok.\n",
2077 cli->cli->desthost,
2078 cli->pipe_name,
2079 (unsigned int)cli->fnum));
2081 /* Unmarshall the RPC header */
2082 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2083 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2084 prs_mem_free(&rbuf);
2085 return NT_STATUS_BUFFER_TOO_SMALL;
2088 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2089 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2090 prs_mem_free(&rbuf);
2091 return NT_STATUS_BUFFER_TOO_SMALL;
2094 if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
2095 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2096 prs_mem_free(&rbuf);
2097 return NT_STATUS_BUFFER_TOO_SMALL;
2100 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2101 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2103 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2104 switch(auth_type) {
2106 case PIPE_AUTH_TYPE_NONE:
2107 case PIPE_AUTH_TYPE_SCHANNEL:
2108 /* Bind complete. */
2109 break;
2111 case PIPE_AUTH_TYPE_NTLMSSP:
2112 /* Need to send AUTH3 packet - no reply. */
2113 status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
2114 auth_type, auth_level);
2115 if (!NT_STATUS_IS_OK(status)) {
2116 prs_mem_free(&rbuf);
2117 return status;
2119 break;
2121 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2122 /* Need to send alter context request and reply. */
2123 status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
2124 &abstract, &transfer,
2125 auth_type, auth_level);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 prs_mem_free(&rbuf);
2128 return status;
2130 break;
2132 case PIPE_AUTH_TYPE_KRB5:
2133 /* */
2135 default:
2136 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2137 (unsigned int)auth_type ));
2138 prs_mem_free(&rbuf);
2139 return NT_STATUS_INVALID_INFO_CLASS;
2142 /* Pipe is bound - set up auth_type and auth_level data. */
2144 cli->auth.auth_type = auth_type;
2145 cli->auth.auth_level = auth_level;
2147 prs_mem_free(&rbuf);
2148 return NT_STATUS_OK;
2151 /****************************************************************************
2152 Open a named pipe over SMB to a remote server.
2153 ****************************************************************************/
2155 static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2157 TALLOC_CTX *mem_ctx;
2158 struct rpc_pipe_client *result;
2159 int fnum;
2161 *perr = NT_STATUS_NO_MEMORY;
2163 /* The pipe name index must fall within our array */
2164 SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
2166 mem_ctx = talloc_init("struct rpc_pipe_client");
2167 if (mem_ctx == NULL) {
2168 return NULL;
2171 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2172 if (result == NULL) {
2173 return NULL;
2176 result->mem_ctx = mem_ctx;
2178 result->pipe_name = cli_get_pipe_name(pipe_idx);
2180 fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
2182 if (fnum == -1) {
2183 DEBUG(0,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
2184 "to machine %s. Error was %s\n",
2185 result->pipe_name, cli->desthost,
2186 cli_errstr(cli)));
2187 *perr = cli_get_nt_error(cli);
2188 talloc_destroy(result->mem_ctx);
2189 return NULL;
2192 result->fnum = fnum;
2193 result->cli = cli;
2194 result->pipe_idx = pipe_idx;
2195 result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
2196 result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
2198 if (pipe_idx == PI_NETLOGON) {
2199 /* Set up a netlogon credential chain for a netlogon pipe. */
2200 result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
2201 if (result->dc == NULL) {
2202 talloc_destroy(result->mem_ctx);
2203 return NULL;
2207 DLIST_ADD(cli->pipe_list, result);
2208 *perr = NT_STATUS_OK;
2210 return result;
2213 /****************************************************************************
2214 Open a named pipe to an SMB server and bind anonymously.
2215 ****************************************************************************/
2217 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2219 struct rpc_pipe_client *result;
2221 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2222 if (result == NULL) {
2223 return NULL;
2226 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
2227 if (!NT_STATUS_IS_OK(*perr)) {
2228 DEBUG(0, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
2229 cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
2230 cli_rpc_pipe_close(result);
2231 return NULL;
2234 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
2235 result->pipe_name, cli->desthost ));
2237 return result;
2240 /****************************************************************************
2241 Free function for NTLMSSP auth.
2242 ****************************************************************************/
2244 static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
2246 if (auth->a_u.ntlmssp_state) {
2247 ntlmssp_end(&auth->a_u.ntlmssp_state);
2248 auth->a_u.ntlmssp_state = NULL;
2252 /****************************************************************************
2253 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2254 ****************************************************************************/
2256 static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
2257 int pipe_idx,
2258 enum pipe_auth_type auth_type,
2259 enum pipe_auth_level auth_level,
2260 const char *domain,
2261 const char *username,
2262 const char *password,
2263 NTSTATUS *perr)
2265 struct rpc_pipe_client *result;
2266 NTLMSSP_STATE *ntlmssp_state = NULL;
2268 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2269 if (result == NULL) {
2270 return NULL;
2273 result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
2275 result->domain = domain;
2276 result->user_name = username;
2277 pwd_set_cleartext(&result->pwd, password);
2279 *perr = ntlmssp_client_start(&ntlmssp_state);
2280 if (!NT_STATUS_IS_OK(*perr)) {
2281 goto err;
2284 result->auth.a_u.ntlmssp_state = ntlmssp_state;
2286 *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name);
2287 if (!NT_STATUS_IS_OK(*perr)) {
2288 goto err;
2291 *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain);
2292 if (!NT_STATUS_IS_OK(*perr)) {
2293 goto err;
2296 if (cli->pwd.null_pwd) {
2297 *perr = ntlmssp_set_password(ntlmssp_state, NULL);
2298 if (!NT_STATUS_IS_OK(*perr)) {
2299 goto err;
2301 } else {
2302 *perr = ntlmssp_set_password(ntlmssp_state, password);
2303 if (!NT_STATUS_IS_OK(*perr)) {
2304 goto err;
2308 /* Turn off sign+seal to allow selected auth level to turn it back on. */
2309 ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
2311 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2312 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2313 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2314 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2317 *perr = rpc_pipe_bind(result, auth_type, auth_level);
2318 if (!NT_STATUS_IS_OK(*perr)) {
2319 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2320 nt_errstr(*perr) ));
2321 goto err;
2324 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to machine %s and"
2325 "bound NTLMSSP as user %s\\%s.\n",
2326 result->pipe_name, cli->desthost,
2327 domain, username ));
2329 return result;
2331 err:
2333 cli_rpc_pipe_close(result);
2334 return NULL;
2337 /****************************************************************************
2338 External interface.
2339 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
2340 ****************************************************************************/
2342 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2343 int pipe_idx,
2344 enum pipe_auth_level auth_level,
2345 const char *domain,
2346 const char *username,
2347 const char *password,
2348 NTSTATUS *perr)
2350 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2351 pipe_idx,
2352 PIPE_AUTH_TYPE_NTLMSSP,
2353 auth_level,
2354 domain,
2355 username,
2356 password,
2357 perr);
2360 /****************************************************************************
2361 External interface.
2362 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
2363 ****************************************************************************/
2365 struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
2366 int pipe_idx,
2367 enum pipe_auth_level auth_level,
2368 const char *domain,
2369 const char *username,
2370 const char *password,
2371 NTSTATUS *perr)
2373 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2374 pipe_idx,
2375 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
2376 auth_level,
2377 domain,
2378 username,
2379 password,
2380 perr);
2383 /****************************************************************************
2384 Open a netlogon pipe and get the schannel session key.
2385 ****************************************************************************/
2387 static struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
2388 const char *domain,
2389 NTSTATUS *perr)
2391 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
2392 struct rpc_pipe_client *netlogon_pipe = NULL;
2393 uint32 sec_chan_type = 0;
2394 char machine_pwd[16];
2395 fstring machine_account;
2397 netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
2398 if (!netlogon_pipe) {
2399 return NULL;
2402 /* Get the machine account credentials from secrets.tdb. */
2403 if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
2404 DEBUG(0, ("get_schannel_session_key: could not fetch "
2405 "trust account password for domain '%s'\n",
2406 domain));
2407 cli_rpc_pipe_close(netlogon_pipe);
2408 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2409 return NULL;
2412 if ( IS_DC ) {
2413 fstrcpy( machine_account, lp_workgroup() );
2414 } else {
2415 /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
2416 if (strequal(domain, lp_workgroup())) {
2417 fstrcpy(machine_account, global_myname());
2418 } else {
2419 fstrcpy(machine_account, domain);
2423 *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
2424 cli->desthost,
2425 domain,
2426 machine_account,
2427 machine_pwd,
2428 sec_chan_type,
2429 &neg_flags);
2431 if (!NT_STATUS_IS_OK(*perr)) {
2432 DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds "
2433 "failed with result %s\n",
2434 nt_errstr(*perr) ));
2435 cli_rpc_pipe_close(netlogon_pipe);
2436 return NULL;
2439 if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) {
2440 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2441 cli->desthost));
2442 cli_rpc_pipe_close(netlogon_pipe);
2443 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
2444 return NULL;
2447 return netlogon_pipe;
2450 /****************************************************************************
2451 External interface.
2452 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2453 using session_key. sign and seal.
2454 ****************************************************************************/
2456 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2457 int pipe_idx,
2458 enum pipe_auth_level auth_level,
2459 const char *domain,
2460 const struct dcinfo *pdc,
2461 NTSTATUS *perr)
2463 struct rpc_pipe_client *result;
2465 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2466 if (result == NULL) {
2467 return NULL;
2470 result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct);
2471 if (!result->auth.a_u.schannel_auth) {
2472 cli_rpc_pipe_close(result);
2473 *perr = NT_STATUS_NO_MEMORY;
2474 return NULL;
2477 result->domain = domain;
2478 memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
2480 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
2481 if (!NT_STATUS_IS_OK(*perr)) {
2482 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
2483 nt_errstr(*perr) ));
2484 cli_rpc_pipe_close(result);
2485 return NULL;
2488 /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
2489 if (result->dc) {
2490 *result->dc = *pdc;
2493 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2494 "for domain %s "
2495 "and bound using schannel.\n",
2496 result->pipe_name, cli->desthost, domain ));
2498 return result;
2501 /****************************************************************************
2502 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2503 Fetch the session key ourselves using a temporary netlogon pipe. This
2504 version uses an ntlmssp auth bound netlogon pipe to get the key.
2505 ****************************************************************************/
2507 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
2508 const char *domain,
2509 const char *username,
2510 const char *password,
2511 NTSTATUS *perr)
2513 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
2514 struct rpc_pipe_client *netlogon_pipe = NULL;
2515 uint32 sec_chan_type = 0;
2516 char machine_pwd[16];
2517 fstring machine_account;
2519 netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
2520 if (!netlogon_pipe) {
2521 return NULL;
2524 /* Get the machine account credentials from secrets.tdb. */
2525 if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
2526 DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch "
2527 "trust account password for domain '%s'\n",
2528 domain));
2529 cli_rpc_pipe_close(netlogon_pipe);
2530 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2531 return NULL;
2534 if ( IS_DC ) {
2535 fstrcpy( machine_account, lp_workgroup() );
2536 } else {
2537 /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
2538 if (strequal(domain, lp_workgroup())) {
2539 fstrcpy(machine_account, global_myname());
2540 } else {
2541 fstrcpy(machine_account, domain);
2545 *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
2546 cli->desthost,
2547 domain,
2548 machine_account,
2549 machine_pwd,
2550 sec_chan_type,
2551 &neg_flags);
2553 if (!NT_STATUS_IS_OK(*perr)) {
2554 DEBUG(3,("get_schannel_session_key_auth_ntlmssp: rpccli_netlogon_setup_creds "
2555 "failed with result %s\n",
2556 nt_errstr(*perr) ));
2557 cli_rpc_pipe_close(netlogon_pipe);
2558 return NULL;
2561 if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) {
2562 DEBUG(3, ("get_schannel_session_key_auth_ntlmssp: Server %s did not offer schannel\n",
2563 cli->desthost));
2564 cli_rpc_pipe_close(netlogon_pipe);
2565 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
2566 return NULL;
2569 return netlogon_pipe;
2572 /****************************************************************************
2573 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2574 Fetch the session key ourselves using a temporary netlogon pipe. This version
2575 uses an ntlmssp bind to get the session key.
2576 ****************************************************************************/
2578 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
2579 int pipe_idx,
2580 enum pipe_auth_level auth_level,
2581 const char *domain,
2582 const char *username,
2583 const char *password,
2584 NTSTATUS *perr)
2586 struct rpc_pipe_client *netlogon_pipe = NULL;
2587 struct rpc_pipe_client *result = NULL;
2589 netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username, password, perr);
2590 if (!netlogon_pipe) {
2591 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
2592 "key from server %s for domain %s.\n",
2593 cli->desthost, domain ));
2594 return NULL;
2597 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2598 auth_level,
2599 domain, netlogon_pipe->dc, perr);
2601 /* Now we've bound using the session key we can close the netlog pipe. */
2602 cli_rpc_pipe_close(netlogon_pipe);
2604 return result;
2607 /****************************************************************************
2608 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2609 Fetch the session key ourselves using a temporary netlogon pipe.
2610 ****************************************************************************/
2612 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
2613 int pipe_idx,
2614 enum pipe_auth_level auth_level,
2615 const char *domain,
2616 NTSTATUS *perr)
2618 struct rpc_pipe_client *netlogon_pipe = NULL;
2619 struct rpc_pipe_client *result = NULL;
2621 netlogon_pipe = get_schannel_session_key(cli, domain, perr);
2622 if (!netlogon_pipe) {
2623 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
2624 "key from server %s for domain %s.\n",
2625 cli->desthost, domain ));
2626 return NULL;
2629 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2630 auth_level,
2631 domain, netlogon_pipe->dc, perr);
2633 /* Now we've bound using the session key we can close the netlog pipe. */
2634 cli_rpc_pipe_close(netlogon_pipe);
2636 return result;
2639 /****************************************************************************
2640 Free function for the kerberos spcific data.
2641 ****************************************************************************/
2643 static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
2645 data_blob_free(&a->a_u.kerberos_auth->session_key);
2648 /****************************************************************************
2649 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
2650 The idea is this can be called with service_princ, username and password all
2651 NULL so long as the caller has a TGT.
2652 ****************************************************************************/
2654 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
2655 int pipe_idx,
2656 enum pipe_auth_level auth_level,
2657 const char *service_princ,
2658 const char *username,
2659 const char *password,
2660 NTSTATUS *perr)
2662 #ifdef HAVE_KRB5
2663 struct rpc_pipe_client *result;
2665 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2666 if (result == NULL) {
2667 return NULL;
2670 /* Default service principal is "host/server@realm" */
2671 if (!service_princ) {
2672 service_princ = talloc_asprintf(result->mem_ctx, "host/%s@%s",
2673 cli->desthost, lp_realm() );
2674 if (!service_princ) {
2675 cli_rpc_pipe_close(result);
2676 return NULL;
2680 /* Only get a new TGT if username/password are given. */
2681 if (username && password) {
2682 int ret = kerberos_kinit_password(username, password, 0, NULL, NULL);
2683 if (ret) {
2684 cli_rpc_pipe_close(result);
2685 return NULL;
2689 result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(cli->mem_ctx, struct kerberos_auth_struct);
2690 if (!result->auth.a_u.kerberos_auth) {
2691 cli_rpc_pipe_close(result);
2692 *perr = NT_STATUS_NO_MEMORY;
2693 return NULL;
2696 result->auth.a_u.kerberos_auth->service_principal = service_princ;
2697 result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
2699 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
2700 if (!NT_STATUS_IS_OK(*perr)) {
2701 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
2702 nt_errstr(*perr) ));
2703 cli_rpc_pipe_close(result);
2704 return NULL;
2707 return result;
2708 #else
2709 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
2710 return NULL;
2711 #endif
2714 #if 0 /* Moved to libsmb/clientgen.c */
2715 /****************************************************************************
2716 External interface.
2717 Close an open named pipe over SMB. Free any authentication data.
2718 ****************************************************************************/
2720 void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
2722 if (!cli_close(cli->cli, cli->fnum)) {
2723 DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
2724 "to machine %s. Error was %s\n",
2725 cli->pipe_name),
2726 cli->cli->desthost,
2727 cli_errstr(cli->cli)));
2730 if (cli->auth.cli_auth_data_free_func) {
2731 (*cli->auth.cli_auth_data_free_func)(&cli->auth);
2733 DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
2734 cli->pipe_name, cli->cli->desthost ));
2736 DLIST_REMOVE(cli->cli->pipe_list, cli);
2737 talloc_destroy(cli->mem_ctx);
2739 #endif