Insert space inside this very long string. It is arguable how to fix it properly...
[Samba/bjacke.git] / source3 / rpc_client / cli_pipe.c
blob828307cace852555949486fe61ee88641e4de27e
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"
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_RPC_CLI
25 extern struct pipe_id_info pipe_names[];
27 /********************************************************************
28 Map internal value to wire value.
29 ********************************************************************/
31 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
33 switch (auth_type) {
35 case PIPE_AUTH_TYPE_NONE:
36 return RPC_ANONYMOUS_AUTH_TYPE;
38 case PIPE_AUTH_TYPE_NTLMSSP:
39 return RPC_NTLMSSP_AUTH_TYPE;
41 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
42 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
43 return RPC_SPNEGO_AUTH_TYPE;
45 case PIPE_AUTH_TYPE_SCHANNEL:
46 return RPC_SCHANNEL_AUTH_TYPE;
48 case PIPE_AUTH_TYPE_KRB5:
49 return RPC_KRB5_AUTH_TYPE;
51 default:
52 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
53 "auth type %u\n",
54 (unsigned int)auth_type ));
55 break;
57 return -1;
60 /********************************************************************
61 Rpc pipe call id.
62 ********************************************************************/
64 static uint32 get_rpc_call_id(void)
66 static uint32 call_id = 0;
67 return ++call_id;
70 /*******************************************************************
71 Use SMBreadX to get rest of one fragment's worth of rpc data.
72 Will expand the current_pdu struct to the correct size.
73 ********************************************************************/
75 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
76 prs_struct *current_pdu,
77 uint32 data_to_read,
78 uint32 *current_pdu_offset)
80 size_t size = (size_t)cli->max_recv_frag;
81 uint32 stream_offset = 0;
82 ssize_t num_read;
83 char *pdata;
84 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
86 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
87 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
90 * Grow the buffer if needed to accommodate the data to be read.
93 if (extra_data_size > 0) {
94 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
95 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
96 return NT_STATUS_NO_MEMORY;
98 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
101 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
103 do {
104 /* read data using SMBreadX */
105 if (size > (size_t)data_to_read) {
106 size = (size_t)data_to_read;
109 num_read = cli_read(cli->cli, cli->fnum, pdata,
110 (off_t)stream_offset, size);
112 DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n",
113 (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read));
116 * A dos error of ERRDOS/ERRmoredata is not an error.
118 if (cli_is_dos_error(cli->cli)) {
119 uint32 ecode;
120 uint8 eclass;
121 cli_dos_error(cli->cli, &eclass, &ecode);
122 if (eclass != ERRDOS && ecode != ERRmoredata) {
123 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n",
124 eclass, (unsigned int)ecode,
125 cli_errstr(cli->cli),
126 cli->pipe_name ));
127 return dos_to_ntstatus(eclass, ecode);
132 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
134 if (cli_is_nt_error(cli->cli)) {
135 if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) {
136 DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n",
137 nt_errstr(cli_nt_error(cli->cli)),
138 cli->pipe_name ));
139 return cli_nt_error(cli->cli);
143 if (num_read == -1) {
144 DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n",
145 cli->pipe_name ));
146 return cli_get_nt_error(cli->cli);
149 data_to_read -= num_read;
150 stream_offset += num_read;
151 pdata += num_read;
153 } while (num_read > 0 && data_to_read > 0);
154 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
157 * Update the current offset into current_pdu by the amount read.
159 *current_pdu_offset += stream_offset;
160 return NT_STATUS_OK;
163 /****************************************************************************
164 Try and get a PDU's worth of data from current_pdu. If not, then read more
165 from the wire.
166 ****************************************************************************/
168 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
170 NTSTATUS ret = NT_STATUS_OK;
171 uint32 current_pdu_len = prs_data_size(current_pdu);
173 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
174 if (current_pdu_len < RPC_HEADER_LEN) {
175 /* rpc_read expands the current_pdu struct as neccessary. */
176 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
177 if (!NT_STATUS_IS_OK(ret)) {
178 return ret;
182 /* This next call sets the endian bit correctly in current_pdu. */
183 /* We will propagate this to rbuf later. */
184 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
185 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
186 return NT_STATUS_BUFFER_TOO_SMALL;
189 /* Ensure we have frag_len bytes of data. */
190 if (current_pdu_len < prhdr->frag_len) {
191 /* rpc_read expands the current_pdu struct as neccessary. */
192 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
193 if (!NT_STATUS_IS_OK(ret)) {
194 return ret;
198 if (current_pdu_len < prhdr->frag_len) {
199 return NT_STATUS_BUFFER_TOO_SMALL;
202 return NT_STATUS_OK;
205 /****************************************************************************
206 NTLMSSP specific sign/seal.
207 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
208 In fact I should probably abstract these into identical pieces of code... JRA.
209 ****************************************************************************/
211 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
212 prs_struct *current_pdu,
213 uint8 *p_ss_padding_len)
215 RPC_HDR_AUTH auth_info;
216 uint32 save_offset = prs_offset(current_pdu);
217 uint32 auth_len = prhdr->auth_len;
218 NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state;
219 unsigned char *data = NULL;
220 size_t data_len;
221 unsigned char *full_packet_data = NULL;
222 size_t full_packet_data_len;
223 DATA_BLOB auth_blob;
224 NTSTATUS status;
226 if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
227 return NT_STATUS_OK;
230 if (!ntlmssp_state) {
231 return NT_STATUS_INVALID_PARAMETER;
234 /* Ensure there's enough data for an authenticated response. */
235 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
236 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
237 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
238 (unsigned int)auth_len ));
239 return NT_STATUS_BUFFER_TOO_SMALL;
243 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
244 * after the RPC header.
245 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
246 * functions as NTLMv2 checks the rpc headers also.
249 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
250 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
252 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
253 full_packet_data_len = prhdr->frag_len - auth_len;
255 /* Pull the auth header and the following data into a blob. */
256 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
257 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
258 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
259 return NT_STATUS_BUFFER_TOO_SMALL;
262 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
263 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
264 return NT_STATUS_BUFFER_TOO_SMALL;
267 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
268 auth_blob.length = auth_len;
270 switch (cli->auth.auth_level) {
271 case PIPE_AUTH_LEVEL_PRIVACY:
272 /* Data is encrypted. */
273 status = ntlmssp_unseal_packet(ntlmssp_state,
274 data, data_len,
275 full_packet_data,
276 full_packet_data_len,
277 &auth_blob);
278 if (!NT_STATUS_IS_OK(status)) {
279 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
280 "packet from remote machine %s on pipe %s "
281 "fnum 0x%x. Error was %s.\n",
282 cli->desthost,
283 cli->pipe_name,
284 (unsigned int)cli->fnum,
285 nt_errstr(status) ));
286 return status;
288 break;
289 case PIPE_AUTH_LEVEL_INTEGRITY:
290 /* Data is signed. */
291 status = ntlmssp_check_packet(ntlmssp_state,
292 data, data_len,
293 full_packet_data,
294 full_packet_data_len,
295 &auth_blob);
296 if (!NT_STATUS_IS_OK(status)) {
297 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
298 "packet from remote machine %s on pipe %s "
299 "fnum 0x%x. Error was %s.\n",
300 cli->desthost,
301 cli->pipe_name,
302 (unsigned int)cli->fnum,
303 nt_errstr(status) ));
304 return status;
306 break;
307 default:
308 DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n",
309 cli->auth.auth_level ));
310 return NT_STATUS_INVALID_INFO_CLASS;
314 * Return the current pointer to the data offset.
317 if(!prs_set_offset(current_pdu, save_offset)) {
318 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
319 (unsigned int)save_offset ));
320 return NT_STATUS_BUFFER_TOO_SMALL;
324 * Remember the padding length. We must remove it from the real data
325 * stream once the sign/seal is done.
328 *p_ss_padding_len = auth_info.auth_pad_len;
330 return NT_STATUS_OK;
333 /****************************************************************************
334 schannel specific sign/seal.
335 ****************************************************************************/
337 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
338 prs_struct *current_pdu,
339 uint8 *p_ss_padding_len)
341 RPC_HDR_AUTH auth_info;
342 RPC_AUTH_SCHANNEL_CHK schannel_chk;
343 uint32 auth_len = prhdr->auth_len;
344 uint32 save_offset = prs_offset(current_pdu);
345 struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth;
346 uint32 data_len;
348 if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
349 return NT_STATUS_OK;
352 if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
353 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
354 return NT_STATUS_INVALID_PARAMETER;
357 if (!schannel_auth) {
358 return NT_STATUS_INVALID_PARAMETER;
361 /* Ensure there's enough data for an authenticated response. */
362 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
363 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
364 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
365 (unsigned int)auth_len ));
366 return NT_STATUS_INVALID_PARAMETER;
369 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
371 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
372 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
373 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
374 return NT_STATUS_BUFFER_TOO_SMALL;
377 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
378 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
379 return NT_STATUS_BUFFER_TOO_SMALL;
382 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
383 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
384 auth_info.auth_type));
385 return NT_STATUS_BUFFER_TOO_SMALL;
388 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
389 &schannel_chk, current_pdu, 0)) {
390 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
391 return NT_STATUS_BUFFER_TOO_SMALL;
394 if (!schannel_decode(schannel_auth,
395 cli->auth.auth_level,
396 SENDER_IS_ACCEPTOR,
397 &schannel_chk,
398 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
399 data_len)) {
400 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
401 "Connection to remote machine %s "
402 "pipe %s fnum 0x%x.\n",
403 cli->desthost,
404 cli->pipe_name,
405 (unsigned int)cli->fnum ));
406 return NT_STATUS_INVALID_PARAMETER;
409 /* The sequence number gets incremented on both send and receive. */
410 schannel_auth->seq_num++;
413 * Return the current pointer to the data offset.
416 if(!prs_set_offset(current_pdu, save_offset)) {
417 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
418 (unsigned int)save_offset ));
419 return NT_STATUS_BUFFER_TOO_SMALL;
423 * Remember the padding length. We must remove it from the real data
424 * stream once the sign/seal is done.
427 *p_ss_padding_len = auth_info.auth_pad_len;
429 return NT_STATUS_OK;
432 /****************************************************************************
433 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
434 ****************************************************************************/
436 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
437 prs_struct *current_pdu,
438 uint8 *p_ss_padding_len)
440 NTSTATUS ret = NT_STATUS_OK;
442 /* Paranioa checks for auth_len. */
443 if (prhdr->auth_len) {
444 if (prhdr->auth_len > prhdr->frag_len) {
445 return NT_STATUS_INVALID_PARAMETER;
448 if (prhdr->auth_len + RPC_HDR_AUTH_LEN < prhdr->auth_len ||
449 prhdr->auth_len + RPC_HDR_AUTH_LEN < RPC_HDR_AUTH_LEN) {
450 /* Integer wrap attempt. */
451 return NT_STATUS_INVALID_PARAMETER;
456 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
459 switch(cli->auth.auth_type) {
460 case PIPE_AUTH_TYPE_NONE:
461 if (prhdr->auth_len) {
462 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
463 "pipe %s fnum 0x%x - got non-zero auth len %u.\n",
464 cli->desthost,
465 cli->pipe_name,
466 (unsigned int)cli->fnum,
467 (unsigned int)prhdr->auth_len ));
468 return NT_STATUS_INVALID_PARAMETER;
470 break;
472 case PIPE_AUTH_TYPE_NTLMSSP:
473 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
474 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
475 if (!NT_STATUS_IS_OK(ret)) {
476 return ret;
478 break;
480 case PIPE_AUTH_TYPE_SCHANNEL:
481 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
482 if (!NT_STATUS_IS_OK(ret)) {
483 return ret;
485 break;
487 case PIPE_AUTH_TYPE_KRB5:
488 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
489 default:
490 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
491 "pipe %s fnum %x - unknown internal auth type %u.\n",
492 cli->desthost,
493 cli->pipe_name,
494 (unsigned int)cli->fnum,
495 cli->auth.auth_type ));
496 return NT_STATUS_INVALID_INFO_CLASS;
499 return NT_STATUS_OK;
502 /****************************************************************************
503 Do basic authentication checks on an incoming pdu.
504 ****************************************************************************/
506 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
507 prs_struct *current_pdu,
508 uint8 expected_pkt_type,
509 char **ppdata,
510 uint32 *pdata_len,
511 prs_struct *return_data)
514 NTSTATUS ret = NT_STATUS_OK;
515 uint32 current_pdu_len = prs_data_size(current_pdu);
517 if (current_pdu_len != prhdr->frag_len) {
518 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
519 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
520 return NT_STATUS_INVALID_PARAMETER;
524 * Point the return values at the real data including the RPC
525 * header. Just in case the caller wants it.
527 *ppdata = prs_data_p(current_pdu);
528 *pdata_len = current_pdu_len;
530 /* Ensure we have the correct type. */
531 switch (prhdr->pkt_type) {
532 case RPC_ALTCONTRESP:
533 case RPC_BINDACK:
535 /* Alter context and bind ack share the same packet definitions. */
536 break;
539 case RPC_RESPONSE:
541 RPC_HDR_RESP rhdr_resp;
542 uint8 ss_padding_len = 0;
544 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
545 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
546 return NT_STATUS_BUFFER_TOO_SMALL;
549 /* Here's where we deal with incoming sign/seal. */
550 ret = cli_pipe_validate_rpc_response(cli, prhdr,
551 current_pdu, &ss_padding_len);
552 if (!NT_STATUS_IS_OK(ret)) {
553 return ret;
556 /* Point the return values at the NDR data. Remember to remove any ss padding. */
557 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
559 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
560 return NT_STATUS_BUFFER_TOO_SMALL;
563 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
565 /* Remember to remove the auth footer. */
566 if (prhdr->auth_len) {
567 /* We've already done integer wrap tests on auth_len in
568 cli_pipe_validate_rpc_response(). */
569 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
570 return NT_STATUS_BUFFER_TOO_SMALL;
572 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
575 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
576 current_pdu_len, *pdata_len, ss_padding_len ));
579 * If this is the first reply, and the allocation hint is reasonably, try and
580 * set up the return_data parse_struct to the correct size.
583 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
584 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
585 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
586 "too large to allocate\n",
587 (unsigned int)rhdr_resp.alloc_hint ));
588 return NT_STATUS_NO_MEMORY;
592 break;
595 case RPC_BINDNACK:
596 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
597 "pipe %s fnum 0x%x!\n",
598 cli->desthost,
599 cli->pipe_name,
600 (unsigned int)cli->fnum));
601 /* Use this for now... */
602 return NT_STATUS_NETWORK_ACCESS_DENIED;
604 case RPC_FAULT:
606 RPC_HDR_RESP rhdr_resp;
607 RPC_HDR_FAULT fault_resp;
609 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
610 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
611 return NT_STATUS_BUFFER_TOO_SMALL;
614 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
615 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
616 return NT_STATUS_BUFFER_TOO_SMALL;
619 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
620 "pipe %s fnum 0x%x!\n",
621 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
622 cli->desthost,
623 cli->pipe_name,
624 (unsigned int)cli->fnum));
625 if (NT_STATUS_IS_OK(fault_resp.status)) {
626 return NT_STATUS_UNSUCCESSFUL;
627 } else {
628 return fault_resp.status;
632 default:
633 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
634 "from remote machine %s pipe %s fnum 0x%x!\n",
635 (unsigned int)prhdr->pkt_type,
636 cli->desthost,
637 cli->pipe_name,
638 (unsigned int)cli->fnum));
639 return NT_STATUS_INVALID_INFO_CLASS;
642 if (prhdr->pkt_type != expected_pkt_type) {
643 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
644 "pipe %s fnum %x got an unexpected RPC packet "
645 "type - %u, not %u\n",
646 cli->desthost,
647 cli->pipe_name,
648 (unsigned int)cli->fnum,
649 prhdr->pkt_type,
650 expected_pkt_type));
651 return NT_STATUS_INVALID_INFO_CLASS;
654 /* Do this just before return - we don't want to modify any rpc header
655 data before now as we may have needed to do cryptographic actions on
656 it before. */
658 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
659 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
660 "setting fragment first/last ON.\n"));
661 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
664 return NT_STATUS_OK;
667 /****************************************************************************
668 Ensure we eat the just processed pdu from the current_pdu prs_struct.
669 Normally the frag_len and buffer size will match, but on the first trans
670 reply there is a theoretical chance that buffer size > frag_len, so we must
671 deal with that.
672 ****************************************************************************/
674 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
676 uint32 current_pdu_len = prs_data_size(current_pdu);
678 if (current_pdu_len < prhdr->frag_len) {
679 return NT_STATUS_BUFFER_TOO_SMALL;
682 /* Common case. */
683 if (current_pdu_len == (uint32)prhdr->frag_len) {
684 prs_mem_free(current_pdu);
685 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
686 /* Make current_pdu dynamic with no memory. */
687 prs_give_memory(current_pdu, 0, 0, True);
688 return NT_STATUS_OK;
692 * Oh no ! More data in buffer than we processed in current pdu.
693 * Cheat. Move the data down and shrink the buffer.
696 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
697 current_pdu_len - prhdr->frag_len);
699 /* Remember to set the read offset back to zero. */
700 prs_set_offset(current_pdu, 0);
702 /* Shrink the buffer. */
703 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
704 return NT_STATUS_BUFFER_TOO_SMALL;
707 return NT_STATUS_OK;
710 /****************************************************************************
711 Send data on an rpc pipe via trans. The prs_struct data must be the last
712 pdu fragment of an NDR data stream.
714 Receive response data from an rpc pipe, which may be large...
716 Read the first fragment: unfortunately have to use SMBtrans for the first
717 bit, then SMBreadX for subsequent bits.
719 If first fragment received also wasn't the last fragment, continue
720 getting fragments until we _do_ receive the last fragment.
722 Request/Response PDU's look like the following...
724 |<------------------PDU len----------------------------------------------->|
725 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
727 +------------+-----------------+-------------+---------------+-------------+
728 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
729 +------------+-----------------+-------------+---------------+-------------+
731 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
732 signing & sealing being negotiated.
734 ****************************************************************************/
736 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
737 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
738 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
739 uint8 expected_pkt_type)
741 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
742 char *rparam = NULL;
743 uint32 rparam_len = 0;
744 uint16 setup[2];
745 char *pdata = prs_data_p(data);
746 uint32 data_len = prs_offset(data);
747 char *prdata = NULL;
748 uint32 rdata_len = 0;
749 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
750 uint32 current_rbuf_offset = 0;
751 prs_struct current_pdu;
753 #ifdef DEVELOPER
754 /* Ensure we're not sending too much. */
755 SMB_ASSERT(data_len <= max_data);
756 #endif
758 /* Set up the current pdu parse struct. */
759 prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
761 /* Create setup parameters - must be in native byte order. */
762 setup[0] = TRANSACT_DCERPCCMD;
763 setup[1] = cli->fnum; /* Pipe file handle. */
765 DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
766 cli->desthost,
767 cli->pipe_name,
768 (unsigned int)cli->fnum ));
771 * Send the last (or only) fragment of an RPC request. For small
772 * amounts of data (about 1024 bytes or so) the RPC request and response
773 * appears in a SMBtrans request and response.
776 if (!cli_api_pipe(cli->cli, "\\PIPE\\",
777 setup, 2, 0, /* Setup, length, max */
778 NULL, 0, 0, /* Params, length, max */
779 pdata, data_len, max_data, /* data, length, max */
780 &rparam, &rparam_len, /* return params, len */
781 &prdata, &rdata_len)) /* return data, len */
783 DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x "
784 "returned critical error. Error was %s\n",
785 cli->desthost,
786 cli->pipe_name,
787 (unsigned int)cli->fnum,
788 cli_errstr(cli->cli)));
789 ret = cli_get_nt_error(cli->cli);
790 SAFE_FREE(rparam);
791 SAFE_FREE(prdata);
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->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->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->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;
917 DATA_BLOB tkt_wrapped = data_blob_null;
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, NULL, NULL);
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, 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;
974 DATA_BLOB request = data_blob_null;
975 DATA_BLOB spnego_msg = data_blob_null;
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, 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;
1021 DATA_BLOB request = data_blob_null;
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, 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 = talloc_strdup(cli, lp_workgroup());
1069 if (cli->domain == NULL) {
1070 return NT_STATUS_NO_MEMORY;
1074 init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
1077 * Now marshall the data into the auth parse_struct.
1080 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1081 &schannel_neg, auth_data, 0)) {
1082 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1083 prs_mem_free(auth_data);
1084 return NT_STATUS_NO_MEMORY;
1087 return NT_STATUS_OK;
1090 /*******************************************************************
1091 Creates the internals of a DCE/RPC bind request or alter context PDU.
1092 ********************************************************************/
1094 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1095 prs_struct *rpc_out,
1096 uint32 rpc_call_id,
1097 const RPC_IFACE *abstract,
1098 const RPC_IFACE *transfer,
1099 RPC_HDR_AUTH *phdr_auth,
1100 prs_struct *pauth_info)
1102 RPC_HDR hdr;
1103 RPC_HDR_RB hdr_rb;
1104 RPC_CONTEXT rpc_ctx;
1105 uint16 auth_len = prs_offset(pauth_info);
1106 uint8 ss_padding_len = 0;
1107 uint16 frag_len = 0;
1109 /* create the RPC context. */
1110 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1112 /* create the bind request RPC_HDR_RB */
1113 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1115 /* Start building the frag length. */
1116 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1118 /* Do we need to pad ? */
1119 if (auth_len) {
1120 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1121 if (data_len % 8) {
1122 ss_padding_len = 8 - (data_len % 8);
1123 phdr_auth->auth_pad_len = ss_padding_len;
1125 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1128 /* Create the request RPC_HDR */
1129 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1131 /* Marshall the RPC header */
1132 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1133 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1134 return NT_STATUS_NO_MEMORY;
1137 /* Marshall the bind request data */
1138 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1139 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1140 return NT_STATUS_NO_MEMORY;
1144 * Grow the outgoing buffer to store any auth info.
1147 if(auth_len != 0) {
1148 if (ss_padding_len) {
1149 char pad[8];
1150 memset(pad, '\0', 8);
1151 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1152 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1153 return NT_STATUS_NO_MEMORY;
1157 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1158 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1159 return NT_STATUS_NO_MEMORY;
1163 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1164 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1165 return NT_STATUS_NO_MEMORY;
1169 return NT_STATUS_OK;
1172 /*******************************************************************
1173 Creates a DCE/RPC bind request.
1174 ********************************************************************/
1176 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1177 prs_struct *rpc_out,
1178 uint32 rpc_call_id,
1179 const RPC_IFACE *abstract,
1180 const RPC_IFACE *transfer,
1181 enum pipe_auth_type auth_type,
1182 enum pipe_auth_level auth_level)
1184 RPC_HDR_AUTH hdr_auth;
1185 prs_struct auth_info;
1186 NTSTATUS ret = NT_STATUS_OK;
1188 ZERO_STRUCT(hdr_auth);
1189 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1190 return NT_STATUS_NO_MEMORY;
1192 switch (auth_type) {
1193 case PIPE_AUTH_TYPE_SCHANNEL:
1194 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1195 if (!NT_STATUS_IS_OK(ret)) {
1196 prs_mem_free(&auth_info);
1197 return ret;
1199 break;
1201 case PIPE_AUTH_TYPE_NTLMSSP:
1202 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1203 if (!NT_STATUS_IS_OK(ret)) {
1204 prs_mem_free(&auth_info);
1205 return ret;
1207 break;
1209 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1210 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1211 if (!NT_STATUS_IS_OK(ret)) {
1212 prs_mem_free(&auth_info);
1213 return ret;
1215 break;
1217 case PIPE_AUTH_TYPE_KRB5:
1218 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1219 if (!NT_STATUS_IS_OK(ret)) {
1220 prs_mem_free(&auth_info);
1221 return ret;
1223 break;
1225 case PIPE_AUTH_TYPE_NONE:
1226 break;
1228 default:
1229 /* "Can't" happen. */
1230 return NT_STATUS_INVALID_INFO_CLASS;
1233 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1234 rpc_out,
1235 rpc_call_id,
1236 abstract,
1237 transfer,
1238 &hdr_auth,
1239 &auth_info);
1241 prs_mem_free(&auth_info);
1242 return ret;
1245 /*******************************************************************
1246 Create and add the NTLMSSP sign/seal auth header and data.
1247 ********************************************************************/
1249 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1250 RPC_HDR *phdr,
1251 uint32 ss_padding_len,
1252 prs_struct *outgoing_pdu)
1254 RPC_HDR_AUTH auth_info;
1255 NTSTATUS status;
1256 DATA_BLOB auth_blob = data_blob_null;
1257 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1259 if (!cli->auth.a_u.ntlmssp_state) {
1260 return NT_STATUS_INVALID_PARAMETER;
1263 /* Init and marshall the auth header. */
1264 init_rpc_hdr_auth(&auth_info,
1265 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1266 cli->auth.auth_level,
1267 ss_padding_len,
1268 1 /* context id. */);
1270 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1271 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1272 data_blob_free(&auth_blob);
1273 return NT_STATUS_NO_MEMORY;
1276 switch (cli->auth.auth_level) {
1277 case PIPE_AUTH_LEVEL_PRIVACY:
1278 /* Data portion is encrypted. */
1279 status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
1280 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1281 data_and_pad_len,
1282 (unsigned char *)prs_data_p(outgoing_pdu),
1283 (size_t)prs_offset(outgoing_pdu),
1284 &auth_blob);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 data_blob_free(&auth_blob);
1287 return status;
1289 break;
1291 case PIPE_AUTH_LEVEL_INTEGRITY:
1292 /* Data is signed. */
1293 status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
1294 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1295 data_and_pad_len,
1296 (unsigned char *)prs_data_p(outgoing_pdu),
1297 (size_t)prs_offset(outgoing_pdu),
1298 &auth_blob);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 data_blob_free(&auth_blob);
1301 return status;
1303 break;
1305 default:
1306 /* Can't happen. */
1307 smb_panic("bad auth level");
1308 /* Notreached. */
1309 return NT_STATUS_INVALID_PARAMETER;
1312 /* Finally marshall the blob. */
1314 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1315 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1316 (unsigned int)NTLMSSP_SIG_SIZE));
1317 data_blob_free(&auth_blob);
1318 return NT_STATUS_NO_MEMORY;
1321 data_blob_free(&auth_blob);
1322 return NT_STATUS_OK;
1325 /*******************************************************************
1326 Create and add the schannel sign/seal auth header and data.
1327 ********************************************************************/
1329 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1330 RPC_HDR *phdr,
1331 uint32 ss_padding_len,
1332 prs_struct *outgoing_pdu)
1334 RPC_HDR_AUTH auth_info;
1335 RPC_AUTH_SCHANNEL_CHK verf;
1336 struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
1337 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1338 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1340 if (!sas) {
1341 return NT_STATUS_INVALID_PARAMETER;
1344 /* Init and marshall the auth header. */
1345 init_rpc_hdr_auth(&auth_info,
1346 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1347 cli->auth.auth_level,
1348 ss_padding_len,
1349 1 /* context id. */);
1351 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1352 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1353 return NT_STATUS_NO_MEMORY;
1356 switch (cli->auth.auth_level) {
1357 case PIPE_AUTH_LEVEL_PRIVACY:
1358 case PIPE_AUTH_LEVEL_INTEGRITY:
1359 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1360 sas->seq_num));
1362 schannel_encode(sas,
1363 cli->auth.auth_level,
1364 SENDER_IS_INITIATOR,
1365 &verf,
1366 data_p,
1367 data_and_pad_len);
1369 sas->seq_num++;
1370 break;
1372 default:
1373 /* Can't happen. */
1374 smb_panic("bad auth level");
1375 /* Notreached. */
1376 return NT_STATUS_INVALID_PARAMETER;
1379 /* Finally marshall the blob. */
1380 smb_io_rpc_auth_schannel_chk("",
1381 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1382 &verf,
1383 outgoing_pdu,
1386 return NT_STATUS_OK;
1389 /*******************************************************************
1390 Calculate how much data we're going to send in this packet, also
1391 work out any sign/seal padding length.
1392 ********************************************************************/
1394 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1395 uint32 data_left,
1396 uint16 *p_frag_len,
1397 uint16 *p_auth_len,
1398 uint32 *p_ss_padding)
1400 uint32 data_space, data_len;
1402 switch (cli->auth.auth_level) {
1403 case PIPE_AUTH_LEVEL_NONE:
1404 case PIPE_AUTH_LEVEL_CONNECT:
1405 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1406 data_len = MIN(data_space, data_left);
1407 *p_ss_padding = 0;
1408 *p_auth_len = 0;
1409 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1410 return data_len;
1412 case PIPE_AUTH_LEVEL_INTEGRITY:
1413 case PIPE_AUTH_LEVEL_PRIVACY:
1414 /* Treat the same for all authenticated rpc requests. */
1415 switch(cli->auth.auth_type) {
1416 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1417 case PIPE_AUTH_TYPE_NTLMSSP:
1418 *p_auth_len = NTLMSSP_SIG_SIZE;
1419 break;
1420 case PIPE_AUTH_TYPE_SCHANNEL:
1421 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1422 break;
1423 default:
1424 smb_panic("bad auth type");
1425 break;
1428 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1429 RPC_HDR_AUTH_LEN - *p_auth_len;
1431 data_len = MIN(data_space, data_left);
1432 if (data_len % 8) {
1433 *p_ss_padding = 8 - (data_len % 8);
1435 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1436 data_len + *p_ss_padding + /* data plus padding. */
1437 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1438 return data_len;
1440 default:
1441 smb_panic("bad auth level");
1442 /* Notreached. */
1443 return 0;
1447 /*******************************************************************
1448 External interface.
1449 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1450 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1451 and deals with signing/sealing details.
1452 ********************************************************************/
1454 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1455 uint8 op_num,
1456 prs_struct *in_data,
1457 prs_struct *out_data)
1459 NTSTATUS ret;
1460 uint32 data_left = prs_offset(in_data);
1461 uint32 alloc_hint = prs_offset(in_data);
1462 uint32 data_sent_thistime = 0;
1463 uint32 current_data_offset = 0;
1464 uint32 call_id = get_rpc_call_id();
1465 char pad[8];
1466 prs_struct outgoing_pdu;
1468 memset(pad, '\0', 8);
1470 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1471 /* Server is screwed up ! */
1472 return NT_STATUS_INVALID_PARAMETER;
1475 if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1476 return NT_STATUS_NO_MEMORY;
1478 while (1) {
1479 RPC_HDR hdr;
1480 RPC_HDR_REQ hdr_req;
1481 uint16 auth_len = 0;
1482 uint16 frag_len = 0;
1483 uint8 flags = 0;
1484 uint32 ss_padding = 0;
1486 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1487 &frag_len, &auth_len, &ss_padding);
1489 if (current_data_offset == 0) {
1490 flags = RPC_FLG_FIRST;
1493 if (data_sent_thistime == data_left) {
1494 flags |= RPC_FLG_LAST;
1497 /* Create and marshall the header and request header. */
1498 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1500 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1501 prs_mem_free(&outgoing_pdu);
1502 return NT_STATUS_NO_MEMORY;
1505 /* Create the rpc request RPC_HDR_REQ */
1506 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1508 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1509 prs_mem_free(&outgoing_pdu);
1510 return NT_STATUS_NO_MEMORY;
1513 /* Copy in the data, plus any ss padding. */
1514 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1515 prs_mem_free(&outgoing_pdu);
1516 return NT_STATUS_NO_MEMORY;
1519 /* Copy the sign/seal padding data. */
1520 if (ss_padding) {
1521 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1522 prs_mem_free(&outgoing_pdu);
1523 return NT_STATUS_NO_MEMORY;
1527 /* Generate any auth sign/seal and add the auth footer. */
1528 if (auth_len) {
1529 switch (cli->auth.auth_type) {
1530 case PIPE_AUTH_TYPE_NONE:
1531 break;
1532 case PIPE_AUTH_TYPE_NTLMSSP:
1533 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1534 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1535 if (!NT_STATUS_IS_OK(ret)) {
1536 prs_mem_free(&outgoing_pdu);
1537 return ret;
1539 break;
1540 case PIPE_AUTH_TYPE_SCHANNEL:
1541 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1542 if (!NT_STATUS_IS_OK(ret)) {
1543 prs_mem_free(&outgoing_pdu);
1544 return ret;
1546 break;
1547 default:
1548 smb_panic("bad auth type");
1549 break; /* notreached */
1553 /* Actually send the packet. */
1554 if (flags & RPC_FLG_LAST) {
1555 /* Last packet - send the data, get the reply and return. */
1556 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1557 prs_mem_free(&outgoing_pdu);
1559 if (DEBUGLEVEL >= 50) {
1560 char *dump_name = NULL;
1561 /* Also capture received data */
1562 if (asprintf(&dump_name, "%s/reply_%s_%d",
1563 get_dyn_LOGFILEBASE(), cli->pipe_name,
1564 op_num) > 0) {
1565 prs_dump(dump_name, op_num, out_data);
1566 SAFE_FREE(dump_name);
1570 return ret;
1571 } else {
1572 /* More packets to come - write and continue. */
1573 ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
1574 prs_data_p(&outgoing_pdu),
1575 (off_t)0,
1576 (size_t)hdr.frag_len);
1578 if (num_written != hdr.frag_len) {
1579 prs_mem_free(&outgoing_pdu);
1580 return cli_get_nt_error(cli->cli);
1584 current_data_offset += data_sent_thistime;
1585 data_left -= data_sent_thistime;
1587 /* Reset the marshalling position back to zero. */
1588 if (!prs_set_offset(&outgoing_pdu, 0)) {
1589 prs_mem_free(&outgoing_pdu);
1590 return NT_STATUS_NO_MEMORY;
1594 #if 0
1595 /****************************************************************************
1596 Set the handle state.
1597 ****************************************************************************/
1599 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1600 const char *pipe_name, uint16 device_state)
1602 bool state_set = False;
1603 char param[2];
1604 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1605 char *rparam = NULL;
1606 char *rdata = NULL;
1607 uint32 rparam_len, rdata_len;
1609 if (pipe_name == NULL)
1610 return False;
1612 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1613 cli->fnum, pipe_name, device_state));
1615 /* create parameters: device state */
1616 SSVAL(param, 0, device_state);
1618 /* create setup parameters. */
1619 setup[0] = 0x0001;
1620 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1622 /* send the data on \PIPE\ */
1623 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1624 setup, 2, 0, /* setup, length, max */
1625 param, 2, 0, /* param, length, max */
1626 NULL, 0, 1024, /* data, length, max */
1627 &rparam, &rparam_len, /* return param, length */
1628 &rdata, &rdata_len)) /* return data, length */
1630 DEBUG(5, ("Set Handle state: return OK\n"));
1631 state_set = True;
1634 SAFE_FREE(rparam);
1635 SAFE_FREE(rdata);
1637 return state_set;
1639 #endif
1641 /****************************************************************************
1642 Check the rpc bind acknowledge response.
1643 ****************************************************************************/
1645 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1647 if ( hdr_ba->addr.len == 0) {
1648 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1651 /* check the transfer syntax */
1652 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1653 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1654 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1655 return False;
1658 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1659 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1660 hdr_ba->res.num_results, hdr_ba->res.reason));
1663 DEBUG(5,("check_bind_response: accepted!\n"));
1664 return True;
1667 /*******************************************************************
1668 Creates a DCE/RPC bind authentication response.
1669 This is the packet that is sent back to the server once we
1670 have received a BIND-ACK, to finish the third leg of
1671 the authentication handshake.
1672 ********************************************************************/
1674 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1675 uint32 rpc_call_id,
1676 enum pipe_auth_type auth_type,
1677 enum pipe_auth_level auth_level,
1678 DATA_BLOB *pauth_blob,
1679 prs_struct *rpc_out)
1681 RPC_HDR hdr;
1682 RPC_HDR_AUTH hdr_auth;
1683 uint32 pad = 0;
1685 /* Create the request RPC_HDR */
1686 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1687 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1688 pauth_blob->length );
1690 /* Marshall it. */
1691 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1692 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1693 return NT_STATUS_NO_MEMORY;
1697 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1698 about padding - shouldn't this pad to length 8 ? JRA.
1701 /* 4 bytes padding. */
1702 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1703 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1704 return NT_STATUS_NO_MEMORY;
1707 /* Create the request RPC_HDR_AUTHA */
1708 init_rpc_hdr_auth(&hdr_auth,
1709 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1710 auth_level, 0, 1);
1712 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1713 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1714 return NT_STATUS_NO_MEMORY;
1718 * Append the auth data to the outgoing buffer.
1721 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1722 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1723 return NT_STATUS_NO_MEMORY;
1726 return NT_STATUS_OK;
1729 /****************************************************************************
1730 Create and send the third packet in an RPC auth.
1731 ****************************************************************************/
1733 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1734 RPC_HDR *phdr,
1735 prs_struct *rbuf,
1736 uint32 rpc_call_id,
1737 enum pipe_auth_type auth_type,
1738 enum pipe_auth_level auth_level)
1740 DATA_BLOB server_response = data_blob_null;
1741 DATA_BLOB client_reply = data_blob_null;
1742 RPC_HDR_AUTH hdr_auth;
1743 NTSTATUS nt_status;
1744 prs_struct rpc_out;
1745 ssize_t ret;
1747 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1748 return NT_STATUS_INVALID_PARAMETER;
1751 /* Process the returned NTLMSSP blob first. */
1752 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1753 return NT_STATUS_INVALID_PARAMETER;
1756 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1757 return NT_STATUS_INVALID_PARAMETER;
1760 /* TODO - check auth_type/auth_level match. */
1762 server_response = data_blob(NULL, phdr->auth_len);
1763 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1765 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1766 server_response,
1767 &client_reply);
1769 if (!NT_STATUS_IS_OK(nt_status)) {
1770 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1771 data_blob_free(&server_response);
1772 return nt_status;
1775 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1777 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1778 auth_type, auth_level,
1779 &client_reply, &rpc_out);
1781 if (!NT_STATUS_IS_OK(nt_status)) {
1782 prs_mem_free(&rpc_out);
1783 data_blob_free(&client_reply);
1784 data_blob_free(&server_response);
1785 return nt_status;
1788 /* 8 here is named pipe message mode. */
1789 ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
1790 (size_t)prs_offset(&rpc_out));
1792 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1793 DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
1794 prs_mem_free(&rpc_out);
1795 data_blob_free(&client_reply);
1796 data_blob_free(&server_response);
1797 return cli_get_nt_error(cli->cli);
1800 DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
1801 "fnum 0x%x sent auth3 response ok.\n",
1802 cli->desthost,
1803 cli->pipe_name,
1804 (unsigned int)cli->fnum));
1806 prs_mem_free(&rpc_out);
1807 data_blob_free(&client_reply);
1808 data_blob_free(&server_response);
1809 return NT_STATUS_OK;
1812 /*******************************************************************
1813 Creates a DCE/RPC bind alter context authentication request which
1814 may contain a spnego auth blobl
1815 ********************************************************************/
1817 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
1818 const RPC_IFACE *abstract,
1819 const RPC_IFACE *transfer,
1820 enum pipe_auth_level auth_level,
1821 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1822 prs_struct *rpc_out)
1824 RPC_HDR_AUTH hdr_auth;
1825 prs_struct auth_info;
1826 NTSTATUS ret = NT_STATUS_OK;
1828 ZERO_STRUCT(hdr_auth);
1829 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1830 return NT_STATUS_NO_MEMORY;
1832 /* We may change the pad length before marshalling. */
1833 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1835 if (pauth_blob->length) {
1836 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
1837 prs_mem_free(&auth_info);
1838 return NT_STATUS_NO_MEMORY;
1842 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
1843 rpc_out,
1844 rpc_call_id,
1845 abstract,
1846 transfer,
1847 &hdr_auth,
1848 &auth_info);
1849 prs_mem_free(&auth_info);
1850 return ret;
1853 /*******************************************************************
1854 Third leg of the SPNEGO bind mechanism - sends alter context PDU
1855 and gets a response.
1856 ********************************************************************/
1858 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
1859 RPC_HDR *phdr,
1860 prs_struct *rbuf,
1861 uint32 rpc_call_id,
1862 const RPC_IFACE *abstract,
1863 const RPC_IFACE *transfer,
1864 enum pipe_auth_type auth_type,
1865 enum pipe_auth_level auth_level)
1867 DATA_BLOB server_spnego_response = data_blob_null;
1868 DATA_BLOB server_ntlm_response = data_blob_null;
1869 DATA_BLOB client_reply = data_blob_null;
1870 DATA_BLOB tmp_blob = data_blob_null;
1871 RPC_HDR_AUTH hdr_auth;
1872 NTSTATUS nt_status;
1873 prs_struct rpc_out;
1875 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1876 return NT_STATUS_INVALID_PARAMETER;
1879 /* Process the returned NTLMSSP blob first. */
1880 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1881 return NT_STATUS_INVALID_PARAMETER;
1884 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1885 return NT_STATUS_INVALID_PARAMETER;
1888 server_spnego_response = data_blob(NULL, phdr->auth_len);
1889 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1891 /* The server might give us back two challenges - tmp_blob is for the second. */
1892 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
1893 data_blob_free(&server_spnego_response);
1894 data_blob_free(&server_ntlm_response);
1895 data_blob_free(&tmp_blob);
1896 return NT_STATUS_INVALID_PARAMETER;
1899 /* We're finished with the server spnego response and the tmp_blob. */
1900 data_blob_free(&server_spnego_response);
1901 data_blob_free(&tmp_blob);
1903 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1904 server_ntlm_response,
1905 &client_reply);
1907 /* Finished with the server_ntlm response */
1908 data_blob_free(&server_ntlm_response);
1910 if (!NT_STATUS_IS_OK(nt_status)) {
1911 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
1912 data_blob_free(&client_reply);
1913 return nt_status;
1916 /* SPNEGO wrap the client reply. */
1917 tmp_blob = spnego_gen_auth(client_reply);
1918 data_blob_free(&client_reply);
1919 client_reply = tmp_blob;
1920 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
1922 /* Now prepare the alter context pdu. */
1923 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1925 nt_status = create_rpc_alter_context(rpc_call_id,
1926 abstract,
1927 transfer,
1928 auth_level,
1929 &client_reply,
1930 &rpc_out);
1932 data_blob_free(&client_reply);
1934 if (!NT_STATUS_IS_OK(nt_status)) {
1935 prs_mem_free(&rpc_out);
1936 return nt_status;
1939 /* Initialize the returning data struct. */
1940 prs_mem_free(rbuf);
1941 prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
1943 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
1944 if (!NT_STATUS_IS_OK(nt_status)) {
1945 prs_mem_free(&rpc_out);
1946 return nt_status;
1949 prs_mem_free(&rpc_out);
1951 /* Get the auth blob from the reply. */
1952 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
1953 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
1954 return NT_STATUS_BUFFER_TOO_SMALL;
1957 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1958 return NT_STATUS_INVALID_PARAMETER;
1961 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1962 return NT_STATUS_INVALID_PARAMETER;
1965 server_spnego_response = data_blob(NULL, phdr->auth_len);
1966 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1968 /* Check we got a valid auth response. */
1969 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
1970 data_blob_free(&server_spnego_response);
1971 data_blob_free(&tmp_blob);
1972 return NT_STATUS_INVALID_PARAMETER;
1975 data_blob_free(&server_spnego_response);
1976 data_blob_free(&tmp_blob);
1978 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
1979 "remote machine %s pipe %s fnum 0x%x.\n",
1980 cli->desthost,
1981 cli->pipe_name,
1982 (unsigned int)cli->fnum));
1984 return NT_STATUS_OK;
1987 /****************************************************************************
1988 Do an rpc bind.
1989 ****************************************************************************/
1991 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1992 enum pipe_auth_type auth_type,
1993 enum pipe_auth_level auth_level)
1995 RPC_HDR hdr;
1996 RPC_HDR_BA hdr_ba;
1997 prs_struct rpc_out;
1998 prs_struct rbuf;
1999 uint32 rpc_call_id;
2000 NTSTATUS status;
2002 DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
2003 (unsigned int)cli->fnum,
2004 cli->pipe_name,
2005 (unsigned int)auth_type,
2006 (unsigned int)auth_level ));
2008 prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2010 rpc_call_id = get_rpc_call_id();
2012 /* Marshall the outgoing data. */
2013 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2014 cli->abstract_syntax,
2015 cli->transfer_syntax,
2016 auth_type,
2017 auth_level);
2019 if (!NT_STATUS_IS_OK(status)) {
2020 prs_mem_free(&rpc_out);
2021 return status;
2024 /* Initialize the incoming data struct. */
2025 prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2027 /* send data on \PIPE\. receive a response */
2028 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2029 if (!NT_STATUS_IS_OK(status)) {
2030 prs_mem_free(&rpc_out);
2031 return status;
2034 prs_mem_free(&rpc_out);
2036 DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
2037 "fnum 0x%x bind request returned ok.\n",
2038 cli->desthost,
2039 cli->pipe_name,
2040 (unsigned int)cli->fnum));
2042 /* Unmarshall the RPC header */
2043 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2044 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2045 prs_mem_free(&rbuf);
2046 return NT_STATUS_BUFFER_TOO_SMALL;
2049 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2050 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2051 prs_mem_free(&rbuf);
2052 return NT_STATUS_BUFFER_TOO_SMALL;
2055 if(!check_bind_response(&hdr_ba, cli->transfer_syntax)) {
2056 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2057 prs_mem_free(&rbuf);
2058 return NT_STATUS_BUFFER_TOO_SMALL;
2061 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2062 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2064 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2065 switch(auth_type) {
2067 case PIPE_AUTH_TYPE_NONE:
2068 case PIPE_AUTH_TYPE_SCHANNEL:
2069 /* Bind complete. */
2070 break;
2072 case PIPE_AUTH_TYPE_NTLMSSP:
2073 /* Need to send AUTH3 packet - no reply. */
2074 status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
2075 auth_type, auth_level);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 prs_mem_free(&rbuf);
2078 return status;
2080 break;
2082 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2083 /* Need to send alter context request and reply. */
2084 status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
2085 cli->abstract_syntax,
2086 cli->transfer_syntax,
2087 auth_type, auth_level);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 prs_mem_free(&rbuf);
2090 return status;
2092 break;
2094 case PIPE_AUTH_TYPE_KRB5:
2095 /* */
2097 default:
2098 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2099 (unsigned int)auth_type ));
2100 prs_mem_free(&rbuf);
2101 return NT_STATUS_INVALID_INFO_CLASS;
2104 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2105 if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2106 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2107 if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2108 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2109 prs_mem_free(&rbuf);
2110 return NT_STATUS_INVALID_PARAMETER;
2113 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2114 if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2115 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2116 prs_mem_free(&rbuf);
2117 return NT_STATUS_INVALID_PARAMETER;
2122 /* Pipe is bound - set up auth_type and auth_level data. */
2124 cli->auth.auth_type = auth_type;
2125 cli->auth.auth_level = auth_level;
2127 prs_mem_free(&rbuf);
2128 return NT_STATUS_OK;
2131 unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
2132 unsigned int timeout)
2134 return cli_set_timeout(cli->cli, timeout);
2137 bool rpccli_is_pipe_idx(struct rpc_pipe_client *cli, int pipe_idx)
2139 return (cli->abstract_syntax == pipe_names[pipe_idx].abstr_syntax);
2142 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16])
2144 if (!((cli->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2145 || (cli->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
2146 E_md4hash(cli->cli->pwd.password, nt_hash);
2147 return true;
2150 memcpy(nt_hash, cli->auth.a_u.ntlmssp_state->nt_hash, 16);
2151 return true;
2154 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
2156 return p->cli;
2159 static int rpc_pipe_destructor(struct rpc_pipe_client *p)
2161 bool ret;
2163 ret = cli_close(p->cli, p->fnum);
2164 if (!ret) {
2165 DEBUG(1, ("rpc_pipe_destructor: cli_close failed on pipe %s, "
2166 "fnum 0x%x to machine %s. Error was %s\n",
2167 p->pipe_name, (int) p->fnum,
2168 p->desthost, cli_errstr(p->cli)));
2171 if (p->auth.cli_auth_data_free_func) {
2172 (*p->auth.cli_auth_data_free_func)(&p->auth);
2175 DEBUG(10, ("rpc_pipe_destructor: closed pipe %s to machine %s\n",
2176 p->pipe_name, p->desthost ));
2178 DLIST_REMOVE(p->cli->pipe_list, p);
2180 return ret ? -1 : 0;
2183 /****************************************************************************
2184 Open a named pipe over SMB to a remote server.
2186 * CAVEAT CALLER OF THIS FUNCTION:
2187 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2188 * so be sure that this function is called AFTER any structure (vs pointer)
2189 * assignment of the cli. In particular, libsmbclient does structure
2190 * assignments of cli, which invalidates the data in the returned
2191 * rpc_pipe_client if this function is called before the structure assignment
2192 * of cli.
2194 ****************************************************************************/
2196 static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2198 struct rpc_pipe_client *result;
2199 int fnum;
2201 *perr = NT_STATUS_NO_MEMORY;
2203 /* sanity check to protect against crashes */
2205 if ( !cli ) {
2206 *perr = NT_STATUS_INVALID_HANDLE;
2207 return NULL;
2210 /* The pipe name index must fall within our array */
2211 SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
2213 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2214 if (result == NULL) {
2215 *perr = NT_STATUS_NO_MEMORY;
2216 return NULL;
2219 result->pipe_name = cli_get_pipe_name(pipe_idx);
2221 result->cli = cli;
2222 result->abstract_syntax = pipe_names[pipe_idx].abstr_syntax;
2223 result->transfer_syntax = pipe_names[pipe_idx].trans_syntax;
2224 result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
2225 result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
2227 result->domain = talloc_strdup(result, cli->domain);
2228 result->user_name = talloc_strdup(result, cli->user_name);
2229 result->desthost = talloc_strdup(result, cli->desthost);
2230 result->srv_name_slash = talloc_asprintf_strupper_m(
2231 result, "\\\\%s", result->desthost);
2233 if ((result->domain == NULL)
2234 || (result->user_name == NULL)
2235 || (result->desthost == NULL)
2236 || (result->srv_name_slash == NULL)) {
2237 *perr = NT_STATUS_NO_MEMORY;
2238 TALLOC_FREE(result);
2239 return NULL;
2242 if (pipe_idx == PI_NETLOGON) {
2243 /* Set up a netlogon credential chain for a netlogon pipe. */
2244 result->dc = TALLOC_ZERO_P(result, struct dcinfo);
2245 if (result->dc == NULL) {
2246 *perr = NT_STATUS_NO_MEMORY;
2247 TALLOC_FREE(result);
2248 return NULL;
2252 fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
2253 if (fnum == -1) {
2254 DEBUG(1,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
2255 "to machine %s. Error was %s\n",
2256 result->pipe_name, cli->desthost,
2257 cli_errstr(cli)));
2258 *perr = cli_get_nt_error(cli);
2259 talloc_destroy(result);
2260 return NULL;
2263 result->fnum = fnum;
2265 DLIST_ADD(cli->pipe_list, result);
2266 talloc_set_destructor(result, rpc_pipe_destructor);
2268 *perr = NT_STATUS_OK;
2270 return result;
2273 /****************************************************************************
2274 Open a named pipe to an SMB server and bind anonymously.
2275 ****************************************************************************/
2277 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2279 struct rpc_pipe_client *result;
2281 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2282 if (result == NULL) {
2283 return NULL;
2286 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
2287 if (!NT_STATUS_IS_OK(*perr)) {
2288 int lvl = 0;
2289 if (rpccli_is_pipe_idx(result, PI_DSSETUP)) {
2290 /* non AD domains just don't have this pipe, avoid
2291 * level 0 statement in that case - gd */
2292 lvl = 3;
2294 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
2295 cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
2296 TALLOC_FREE(result);
2297 return NULL;
2300 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
2301 result->pipe_name, cli->desthost ));
2303 return result;
2306 /****************************************************************************
2307 Free function for NTLMSSP auth.
2308 ****************************************************************************/
2310 static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
2312 if (auth->a_u.ntlmssp_state) {
2313 ntlmssp_end(&auth->a_u.ntlmssp_state);
2314 auth->a_u.ntlmssp_state = NULL;
2318 /****************************************************************************
2319 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2320 ****************************************************************************/
2322 static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
2323 int pipe_idx,
2324 enum pipe_auth_type auth_type,
2325 enum pipe_auth_level auth_level,
2326 const char *domain,
2327 const char *username,
2328 const char *password,
2329 NTSTATUS *perr)
2331 struct rpc_pipe_client *result;
2332 NTLMSSP_STATE *ntlmssp_state = NULL;
2334 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2335 if (result == NULL) {
2336 return NULL;
2339 result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
2341 TALLOC_FREE(result->domain);
2342 TALLOC_FREE(result->user_name);
2344 result->domain = talloc_strdup(result, domain);
2345 result->user_name = talloc_strdup(result, username);
2347 if ((result->domain == NULL) || (result->user_name == NULL)) {
2348 *perr = NT_STATUS_NO_MEMORY;
2349 goto err;
2352 *perr = ntlmssp_client_start(&ntlmssp_state);
2353 if (!NT_STATUS_IS_OK(*perr)) {
2354 goto err;
2357 result->auth.a_u.ntlmssp_state = ntlmssp_state;
2359 *perr = ntlmssp_set_username(ntlmssp_state, username);
2360 if (!NT_STATUS_IS_OK(*perr)) {
2361 goto err;
2364 *perr = ntlmssp_set_domain(ntlmssp_state, domain);
2365 if (!NT_STATUS_IS_OK(*perr)) {
2366 goto err;
2369 if (cli->pwd.null_pwd) {
2370 *perr = ntlmssp_set_password(ntlmssp_state, NULL);
2371 if (!NT_STATUS_IS_OK(*perr)) {
2372 goto err;
2374 } else {
2375 *perr = ntlmssp_set_password(ntlmssp_state, password);
2376 if (!NT_STATUS_IS_OK(*perr)) {
2377 goto err;
2381 /* Turn off sign+seal to allow selected auth level to turn it back on. */
2382 ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
2384 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2385 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2386 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2387 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2390 *perr = rpc_pipe_bind(result, auth_type, auth_level);
2391 if (!NT_STATUS_IS_OK(*perr)) {
2392 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2393 nt_errstr(*perr) ));
2394 goto err;
2397 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2398 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2399 result->pipe_name, cli->desthost,
2400 domain, username ));
2402 return result;
2404 err:
2406 TALLOC_FREE(result);
2407 return NULL;
2410 /****************************************************************************
2411 External interface.
2412 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
2413 ****************************************************************************/
2415 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2416 int pipe_idx,
2417 enum pipe_auth_level auth_level,
2418 const char *domain,
2419 const char *username,
2420 const char *password,
2421 NTSTATUS *perr)
2423 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2424 pipe_idx,
2425 PIPE_AUTH_TYPE_NTLMSSP,
2426 auth_level,
2427 domain,
2428 username,
2429 password,
2430 perr);
2433 /****************************************************************************
2434 External interface.
2435 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
2436 ****************************************************************************/
2438 struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
2439 int pipe_idx,
2440 enum pipe_auth_level auth_level,
2441 const char *domain,
2442 const char *username,
2443 const char *password,
2444 NTSTATUS *perr)
2446 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2447 pipe_idx,
2448 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
2449 auth_level,
2450 domain,
2451 username,
2452 password,
2453 perr);
2456 /****************************************************************************
2457 Get a the schannel session key out of an already opened netlogon pipe.
2458 ****************************************************************************/
2459 static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2460 struct cli_state *cli,
2461 const char *domain,
2462 uint32 *pneg_flags,
2463 NTSTATUS *perr)
2465 uint32 sec_chan_type = 0;
2466 unsigned char machine_pwd[16];
2467 const char *machine_account;
2469 /* Get the machine account credentials from secrets.tdb. */
2470 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2471 &sec_chan_type))
2473 DEBUG(0, ("get_schannel_session_key: could not fetch "
2474 "trust account password for domain '%s'\n",
2475 domain));
2476 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2477 return false;
2480 *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
2481 cli->desthost, /* server name */
2482 domain, /* domain */
2483 global_myname(), /* client name */
2484 machine_account, /* machine account name */
2485 machine_pwd,
2486 sec_chan_type,
2487 pneg_flags);
2489 if (!NT_STATUS_IS_OK(*perr)) {
2490 DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
2491 "failed with result %s to server %s, domain %s, machine account %s.\n",
2492 nt_errstr(*perr), cli->desthost, domain, machine_account ));
2493 return false;
2496 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
2497 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2498 cli->desthost));
2499 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
2500 return false;
2503 return true;
2506 /****************************************************************************
2507 Open a netlogon pipe and get the schannel session key.
2508 Now exposed to external callers.
2509 ****************************************************************************/
2512 struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
2513 const char *domain,
2514 uint32 *pneg_flags,
2515 NTSTATUS *perr)
2517 struct rpc_pipe_client *netlogon_pipe = NULL;
2519 netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
2520 if (!netlogon_pipe) {
2521 return NULL;
2524 if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2525 pneg_flags, perr))
2527 TALLOC_FREE(netlogon_pipe);
2528 return NULL;
2531 return netlogon_pipe;
2534 /****************************************************************************
2535 External interface.
2536 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2537 using session_key. sign and seal.
2538 ****************************************************************************/
2540 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2541 int pipe_idx,
2542 enum pipe_auth_level auth_level,
2543 const char *domain,
2544 const struct dcinfo *pdc,
2545 NTSTATUS *perr)
2547 struct rpc_pipe_client *result;
2549 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2550 if (result == NULL) {
2551 return NULL;
2554 result->auth.a_u.schannel_auth = TALLOC_ZERO_P(
2555 result, struct schannel_auth_struct);
2556 if (!result->auth.a_u.schannel_auth) {
2557 TALLOC_FREE(result);
2558 *perr = NT_STATUS_NO_MEMORY;
2559 return NULL;
2562 TALLOC_FREE(result->domain);
2563 result->domain = talloc_strdup(result, domain);
2564 if (result->domain == NULL) {
2565 TALLOC_FREE(result);
2566 *perr = NT_STATUS_NO_MEMORY;
2567 return NULL;
2570 memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
2572 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
2573 if (!NT_STATUS_IS_OK(*perr)) {
2574 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
2575 nt_errstr(*perr) ));
2576 TALLOC_FREE(result);
2577 return NULL;
2580 /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
2581 if (result->dc) {
2582 *result->dc = *pdc;
2585 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2586 "for domain %s "
2587 "and bound using schannel.\n",
2588 result->pipe_name, cli->desthost, domain ));
2590 return result;
2593 /****************************************************************************
2594 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2595 Fetch the session key ourselves using a temporary netlogon pipe. This
2596 version uses an ntlmssp auth bound netlogon pipe to get the key.
2597 ****************************************************************************/
2599 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
2600 const char *domain,
2601 const char *username,
2602 const char *password,
2603 uint32 *pneg_flags,
2604 NTSTATUS *perr)
2606 struct rpc_pipe_client *netlogon_pipe = NULL;
2608 netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
2609 if (!netlogon_pipe) {
2610 return NULL;
2613 if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2614 pneg_flags, perr))
2616 TALLOC_FREE(netlogon_pipe);
2617 return NULL;
2620 return netlogon_pipe;
2623 /****************************************************************************
2624 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2625 Fetch the session key ourselves using a temporary netlogon pipe. This version
2626 uses an ntlmssp bind to get the session key.
2627 ****************************************************************************/
2629 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
2630 int pipe_idx,
2631 enum pipe_auth_level auth_level,
2632 const char *domain,
2633 const char *username,
2634 const char *password,
2635 NTSTATUS *perr)
2637 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2638 struct rpc_pipe_client *netlogon_pipe = NULL;
2639 struct rpc_pipe_client *result = NULL;
2641 netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
2642 password, &neg_flags, perr);
2643 if (!netlogon_pipe) {
2644 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
2645 "key from server %s for domain %s.\n",
2646 cli->desthost, domain ));
2647 return NULL;
2650 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2651 auth_level,
2652 domain, netlogon_pipe->dc, perr);
2654 /* Now we've bound using the session key we can close the netlog pipe. */
2655 TALLOC_FREE(netlogon_pipe);
2657 return result;
2660 /****************************************************************************
2661 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2662 Fetch the session key ourselves using a temporary netlogon pipe.
2663 ****************************************************************************/
2665 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
2666 int pipe_idx,
2667 enum pipe_auth_level auth_level,
2668 const char *domain,
2669 NTSTATUS *perr)
2671 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2672 struct rpc_pipe_client *netlogon_pipe = NULL;
2673 struct rpc_pipe_client *result = NULL;
2675 netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
2676 if (!netlogon_pipe) {
2677 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
2678 "key from server %s for domain %s.\n",
2679 cli->desthost, domain ));
2680 return NULL;
2683 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2684 auth_level,
2685 domain, netlogon_pipe->dc, perr);
2687 /* Now we've bound using the session key we can close the netlog pipe. */
2688 TALLOC_FREE(netlogon_pipe);
2690 return result;
2693 #ifdef HAVE_KRB5
2695 /****************************************************************************
2696 Free function for the kerberos spcific data.
2697 ****************************************************************************/
2699 static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
2701 data_blob_free(&a->a_u.kerberos_auth->session_key);
2704 #endif
2706 /****************************************************************************
2707 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
2708 The idea is this can be called with service_princ, username and password all
2709 NULL so long as the caller has a TGT.
2710 ****************************************************************************/
2712 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
2713 int pipe_idx,
2714 enum pipe_auth_level auth_level,
2715 const char *service_princ,
2716 const char *username,
2717 const char *password,
2718 NTSTATUS *perr)
2720 #ifdef HAVE_KRB5
2721 struct rpc_pipe_client *result;
2723 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2724 if (result == NULL) {
2725 return NULL;
2728 /* Default service principal is "desthost$@realm" */
2729 if (!service_princ) {
2730 service_princ = talloc_asprintf(result, "%s$@%s",
2731 cli->desthost, lp_realm() );
2732 if (!service_princ) {
2733 TALLOC_FREE(result);
2734 return NULL;
2738 /* Only get a new TGT if username/password are given. */
2739 if (username && password) {
2740 int ret = kerberos_kinit_password(username, password, 0, NULL);
2741 if (ret) {
2742 TALLOC_FREE(result);
2743 return NULL;
2747 result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(
2748 result, struct kerberos_auth_struct);
2749 if (!result->auth.a_u.kerberos_auth) {
2750 TALLOC_FREE(result);
2751 *perr = NT_STATUS_NO_MEMORY;
2752 return NULL;
2755 result->auth.a_u.kerberos_auth->service_principal = service_princ;
2756 result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
2758 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
2759 if (!NT_STATUS_IS_OK(*perr)) {
2760 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
2761 nt_errstr(*perr) ));
2762 TALLOC_FREE(result);
2763 return NULL;
2766 return result;
2767 #else
2768 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
2769 return NULL;
2770 #endif