Windows 2008 (Longhorn) auth2 flag fixes.
[Samba/nascimento.git] / source3 / rpc_client / cli_pipe.c
blob81b2ea5d68c5e4ccdc03acdc1cd1c0b47b0f2d46
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->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->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->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->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->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->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->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;
633 default:
634 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
635 "from remote machine %s pipe %s fnum 0x%x!\n",
636 (unsigned int)prhdr->pkt_type,
637 cli->cli->desthost,
638 cli->pipe_name,
639 (unsigned int)cli->fnum));
640 return NT_STATUS_INVALID_INFO_CLASS;
643 if (prhdr->pkt_type != expected_pkt_type) {
644 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
645 "pipe %s fnum %x got an unexpected RPC packet "
646 "type - %u, not %u\n",
647 cli->cli->desthost,
648 cli->pipe_name,
649 (unsigned int)cli->fnum,
650 prhdr->pkt_type,
651 expected_pkt_type));
652 return NT_STATUS_INVALID_INFO_CLASS;
655 /* Do this just before return - we don't want to modify any rpc header
656 data before now as we may have needed to do cryptographic actions on
657 it before. */
659 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
660 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
661 "setting fragment first/last ON.\n"));
662 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
665 return NT_STATUS_OK;
668 /****************************************************************************
669 Ensure we eat the just processed pdu from the current_pdu prs_struct.
670 Normally the frag_len and buffer size will match, but on the first trans
671 reply there is a theoretical chance that buffer size > frag_len, so we must
672 deal with that.
673 ****************************************************************************/
675 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
677 uint32 current_pdu_len = prs_data_size(current_pdu);
679 if (current_pdu_len < prhdr->frag_len) {
680 return NT_STATUS_BUFFER_TOO_SMALL;
683 /* Common case. */
684 if (current_pdu_len == (uint32)prhdr->frag_len) {
685 prs_mem_free(current_pdu);
686 prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL);
687 /* Make current_pdu dynamic with no memory. */
688 prs_give_memory(current_pdu, 0, 0, True);
689 return NT_STATUS_OK;
693 * Oh no ! More data in buffer than we processed in current pdu.
694 * Cheat. Move the data down and shrink the buffer.
697 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
698 current_pdu_len - prhdr->frag_len);
700 /* Remember to set the read offset back to zero. */
701 prs_set_offset(current_pdu, 0);
703 /* Shrink the buffer. */
704 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
705 return NT_STATUS_BUFFER_TOO_SMALL;
708 return NT_STATUS_OK;
711 /****************************************************************************
712 Send data on an rpc pipe via trans. The prs_struct data must be the last
713 pdu fragment of an NDR data stream.
715 Receive response data from an rpc pipe, which may be large...
717 Read the first fragment: unfortunately have to use SMBtrans for the first
718 bit, then SMBreadX for subsequent bits.
720 If first fragment received also wasn't the last fragment, continue
721 getting fragments until we _do_ receive the last fragment.
723 Request/Response PDU's look like the following...
725 |<------------------PDU len----------------------------------------------->|
726 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
728 +------------+-----------------+-------------+---------------+-------------+
729 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
730 +------------+-----------------+-------------+---------------+-------------+
732 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
733 signing & sealing being negotiated.
735 ****************************************************************************/
737 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
738 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
739 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
740 uint8 expected_pkt_type)
742 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
743 char *rparam = NULL;
744 uint32 rparam_len = 0;
745 uint16 setup[2];
746 char *pdata = prs_data_p(data);
747 uint32 data_len = prs_offset(data);
748 char *prdata = NULL;
749 uint32 rdata_len = 0;
750 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
751 uint32 current_rbuf_offset = 0;
752 prs_struct current_pdu;
754 #ifdef DEVELOPER
755 /* Ensure we're not sending too much. */
756 SMB_ASSERT(data_len <= max_data);
757 #endif
759 /* Set up the current pdu parse struct. */
760 prs_init(&current_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL);
762 /* Create setup parameters - must be in native byte order. */
763 setup[0] = TRANSACT_DCERPCCMD;
764 setup[1] = cli->fnum; /* Pipe file handle. */
766 DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
767 cli->cli->desthost,
768 cli->pipe_name,
769 (unsigned int)cli->fnum ));
772 * Send the last (or only) fragment of an RPC request. For small
773 * amounts of data (about 1024 bytes or so) the RPC request and response
774 * appears in a SMBtrans request and response.
777 if (!cli_api_pipe(cli->cli, "\\PIPE\\",
778 setup, 2, 0, /* Setup, length, max */
779 NULL, 0, 0, /* Params, length, max */
780 pdata, data_len, max_data, /* data, length, max */
781 &rparam, &rparam_len, /* return params, len */
782 &prdata, &rdata_len)) /* return data, len */
784 DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x "
785 "returned critical error. Error was %s\n",
786 cli->cli->desthost,
787 cli->pipe_name,
788 (unsigned int)cli->fnum,
789 cli_errstr(cli->cli)));
790 ret = cli_get_nt_error(cli->cli);
791 SAFE_FREE(rparam);
792 SAFE_FREE(prdata);
793 goto err;
796 /* Throw away returned params - we know we won't use them. */
798 SAFE_FREE(rparam);
800 if (prdata == NULL) {
801 DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
802 "fnum 0x%x failed to return data.\n",
803 cli->cli->desthost,
804 cli->pipe_name,
805 (unsigned int)cli->fnum));
806 /* Yes - some calls can truely return no data... */
807 prs_mem_free(&current_pdu);
808 return NT_STATUS_OK;
812 * Give this memory as dynamic to the current pdu.
815 prs_give_memory(&current_pdu, prdata, rdata_len, True);
817 /* Ensure we can mess with the return prs_struct. */
818 SMB_ASSERT(UNMARSHALLING(rbuf));
819 SMB_ASSERT(prs_data_size(rbuf) == 0);
821 /* Make rbuf dynamic with no memory. */
822 prs_give_memory(rbuf, 0, 0, True);
824 while(1) {
825 RPC_HDR rhdr;
826 char *ret_data;
827 uint32 ret_data_len;
829 /* Ensure we have enough data for a pdu. */
830 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
831 if (!NT_STATUS_IS_OK(ret)) {
832 goto err;
835 /* We pass in rbuf here so if the alloc hint is set correctly
836 we can set the output size and avoid reallocs. */
838 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
839 &ret_data, &ret_data_len, rbuf);
841 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
842 prs_data_size(&current_pdu), current_rbuf_offset ));
844 if (!NT_STATUS_IS_OK(ret)) {
845 goto err;
848 if ((rhdr.flags & RPC_FLG_FIRST)) {
849 if (rhdr.pack_type[0] == 0) {
850 /* Set the data type correctly for big-endian data on the first packet. */
851 DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
852 "PDU data format is big-endian.\n",
853 cli->cli->desthost,
854 cli->pipe_name,
855 (unsigned int)cli->fnum));
857 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
858 } else {
859 /* Check endianness on subsequent packets. */
860 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
861 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
862 rbuf->bigendian_data ? "big" : "little",
863 current_pdu.bigendian_data ? "big" : "little" ));
864 ret = NT_STATUS_INVALID_PARAMETER;
865 goto err;
870 /* Now copy the data portion out of the pdu into rbuf. */
871 if (!prs_force_grow(rbuf, ret_data_len)) {
872 ret = NT_STATUS_NO_MEMORY;
873 goto err;
875 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
876 current_rbuf_offset += ret_data_len;
878 /* See if we've finished with all the data in current_pdu yet ? */
879 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
880 if (!NT_STATUS_IS_OK(ret)) {
881 goto err;
884 if (rhdr.flags & RPC_FLG_LAST) {
885 break; /* We're done. */
889 DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
890 cli->cli->desthost,
891 cli->pipe_name,
892 (unsigned int)cli->fnum,
893 (unsigned int)prs_data_size(rbuf) ));
895 prs_mem_free(&current_pdu);
896 return NT_STATUS_OK;
898 err:
900 prs_mem_free(&current_pdu);
901 prs_mem_free(rbuf);
902 return ret;
905 /*******************************************************************
906 Creates krb5 auth bind.
907 ********************************************************************/
909 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
910 enum pipe_auth_level auth_level,
911 RPC_HDR_AUTH *pauth_out,
912 prs_struct *auth_data)
914 #ifdef HAVE_KRB5
915 int ret;
916 struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
917 DATA_BLOB tkt = data_blob_null;
918 DATA_BLOB tkt_wrapped = data_blob_null;
920 /* We may change the pad length before marshalling. */
921 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
923 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
924 a->service_principal ));
926 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
928 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
929 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
931 if (ret) {
932 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
933 "failed with %s\n",
934 a->service_principal,
935 error_message(ret) ));
937 data_blob_free(&tkt);
938 prs_mem_free(auth_data);
939 return NT_STATUS_INVALID_PARAMETER;
942 /* wrap that up in a nice GSS-API wrapping */
943 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
945 data_blob_free(&tkt);
947 /* Auth len in the rpc header doesn't include auth_header. */
948 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
949 data_blob_free(&tkt_wrapped);
950 prs_mem_free(auth_data);
951 return NT_STATUS_NO_MEMORY;
954 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
955 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
957 data_blob_free(&tkt_wrapped);
958 return NT_STATUS_OK;
959 #else
960 return NT_STATUS_INVALID_PARAMETER;
961 #endif
964 /*******************************************************************
965 Creates SPNEGO NTLMSSP auth bind.
966 ********************************************************************/
968 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
969 enum pipe_auth_level auth_level,
970 RPC_HDR_AUTH *pauth_out,
971 prs_struct *auth_data)
973 NTSTATUS nt_status;
974 DATA_BLOB null_blob = data_blob_null;
975 DATA_BLOB request = data_blob_null;
976 DATA_BLOB spnego_msg = data_blob_null;
978 /* We may change the pad length before marshalling. */
979 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
981 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
982 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
983 null_blob,
984 &request);
986 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
987 data_blob_free(&request);
988 prs_mem_free(auth_data);
989 return nt_status;
992 /* Wrap this in SPNEGO. */
993 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
995 data_blob_free(&request);
997 /* Auth len in the rpc header doesn't include auth_header. */
998 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
999 data_blob_free(&spnego_msg);
1000 prs_mem_free(auth_data);
1001 return NT_STATUS_NO_MEMORY;
1004 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1005 dump_data(5, spnego_msg.data, spnego_msg.length);
1007 data_blob_free(&spnego_msg);
1008 return NT_STATUS_OK;
1011 /*******************************************************************
1012 Creates NTLMSSP auth bind.
1013 ********************************************************************/
1015 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1016 enum pipe_auth_level auth_level,
1017 RPC_HDR_AUTH *pauth_out,
1018 prs_struct *auth_data)
1020 NTSTATUS nt_status;
1021 DATA_BLOB null_blob = data_blob_null;
1022 DATA_BLOB request = data_blob_null;
1024 /* We may change the pad length before marshalling. */
1025 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1027 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1028 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1029 null_blob,
1030 &request);
1032 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1033 data_blob_free(&request);
1034 prs_mem_free(auth_data);
1035 return nt_status;
1038 /* Auth len in the rpc header doesn't include auth_header. */
1039 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1040 data_blob_free(&request);
1041 prs_mem_free(auth_data);
1042 return NT_STATUS_NO_MEMORY;
1045 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1046 dump_data(5, request.data, request.length);
1048 data_blob_free(&request);
1049 return NT_STATUS_OK;
1052 /*******************************************************************
1053 Creates schannel auth bind.
1054 ********************************************************************/
1056 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1057 enum pipe_auth_level auth_level,
1058 RPC_HDR_AUTH *pauth_out,
1059 prs_struct *auth_data)
1061 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1063 /* We may change the pad length before marshalling. */
1064 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1066 /* Use lp_workgroup() if domain not specified */
1068 if (!cli->domain || !cli->domain[0]) {
1069 cli->domain = lp_workgroup();
1072 init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
1075 * Now marshall the data into the auth parse_struct.
1078 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1079 &schannel_neg, auth_data, 0)) {
1080 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1081 prs_mem_free(auth_data);
1082 return NT_STATUS_NO_MEMORY;
1085 return NT_STATUS_OK;
1088 /*******************************************************************
1089 Creates the internals of a DCE/RPC bind request or alter context PDU.
1090 ********************************************************************/
1092 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1093 prs_struct *rpc_out,
1094 uint32 rpc_call_id,
1095 RPC_IFACE *abstract,
1096 RPC_IFACE *transfer,
1097 RPC_HDR_AUTH *phdr_auth,
1098 prs_struct *pauth_info)
1100 RPC_HDR hdr;
1101 RPC_HDR_RB hdr_rb;
1102 RPC_CONTEXT rpc_ctx;
1103 uint16 auth_len = prs_offset(pauth_info);
1104 uint8 ss_padding_len = 0;
1105 uint16 frag_len = 0;
1107 /* create the RPC context. */
1108 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1110 /* create the bind request RPC_HDR_RB */
1111 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1113 /* Start building the frag length. */
1114 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1116 /* Do we need to pad ? */
1117 if (auth_len) {
1118 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1119 if (data_len % 8) {
1120 ss_padding_len = 8 - (data_len % 8);
1121 phdr_auth->auth_pad_len = ss_padding_len;
1123 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1126 /* Create the request RPC_HDR */
1127 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1129 /* Marshall the RPC header */
1130 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1131 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1132 return NT_STATUS_NO_MEMORY;
1135 /* Marshall the bind request data */
1136 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1137 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1138 return NT_STATUS_NO_MEMORY;
1142 * Grow the outgoing buffer to store any auth info.
1145 if(auth_len != 0) {
1146 if (ss_padding_len) {
1147 char pad[8];
1148 memset(pad, '\0', 8);
1149 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1150 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1151 return NT_STATUS_NO_MEMORY;
1155 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1156 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1157 return NT_STATUS_NO_MEMORY;
1161 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1162 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1163 return NT_STATUS_NO_MEMORY;
1167 return NT_STATUS_OK;
1170 /*******************************************************************
1171 Creates a DCE/RPC bind request.
1172 ********************************************************************/
1174 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1175 prs_struct *rpc_out,
1176 uint32 rpc_call_id,
1177 RPC_IFACE *abstract, RPC_IFACE *transfer,
1178 enum pipe_auth_type auth_type,
1179 enum pipe_auth_level auth_level)
1181 RPC_HDR_AUTH hdr_auth;
1182 prs_struct auth_info;
1183 NTSTATUS ret = NT_STATUS_OK;
1185 ZERO_STRUCT(hdr_auth);
1186 prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
1188 switch (auth_type) {
1189 case PIPE_AUTH_TYPE_SCHANNEL:
1190 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1191 if (!NT_STATUS_IS_OK(ret)) {
1192 prs_mem_free(&auth_info);
1193 return ret;
1195 break;
1197 case PIPE_AUTH_TYPE_NTLMSSP:
1198 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1199 if (!NT_STATUS_IS_OK(ret)) {
1200 prs_mem_free(&auth_info);
1201 return ret;
1203 break;
1205 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1206 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1207 if (!NT_STATUS_IS_OK(ret)) {
1208 prs_mem_free(&auth_info);
1209 return ret;
1211 break;
1213 case PIPE_AUTH_TYPE_KRB5:
1214 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1215 if (!NT_STATUS_IS_OK(ret)) {
1216 prs_mem_free(&auth_info);
1217 return ret;
1219 break;
1221 case PIPE_AUTH_TYPE_NONE:
1222 break;
1224 default:
1225 /* "Can't" happen. */
1226 return NT_STATUS_INVALID_INFO_CLASS;
1229 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1230 rpc_out,
1231 rpc_call_id,
1232 abstract,
1233 transfer,
1234 &hdr_auth,
1235 &auth_info);
1237 prs_mem_free(&auth_info);
1238 return ret;
1241 /*******************************************************************
1242 Create and add the NTLMSSP sign/seal auth header and data.
1243 ********************************************************************/
1245 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1246 RPC_HDR *phdr,
1247 uint32 ss_padding_len,
1248 prs_struct *outgoing_pdu)
1250 RPC_HDR_AUTH auth_info;
1251 NTSTATUS status;
1252 DATA_BLOB auth_blob = data_blob_null;
1253 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1255 if (!cli->auth.a_u.ntlmssp_state) {
1256 return NT_STATUS_INVALID_PARAMETER;
1259 /* Init and marshall the auth header. */
1260 init_rpc_hdr_auth(&auth_info,
1261 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1262 cli->auth.auth_level,
1263 ss_padding_len,
1264 1 /* context id. */);
1266 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1267 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1268 data_blob_free(&auth_blob);
1269 return NT_STATUS_NO_MEMORY;
1272 switch (cli->auth.auth_level) {
1273 case PIPE_AUTH_LEVEL_PRIVACY:
1274 /* Data portion is encrypted. */
1275 status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
1276 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1277 data_and_pad_len,
1278 (unsigned char *)prs_data_p(outgoing_pdu),
1279 (size_t)prs_offset(outgoing_pdu),
1280 &auth_blob);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 data_blob_free(&auth_blob);
1283 return status;
1285 break;
1287 case PIPE_AUTH_LEVEL_INTEGRITY:
1288 /* Data is signed. */
1289 status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
1290 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1291 data_and_pad_len,
1292 (unsigned char *)prs_data_p(outgoing_pdu),
1293 (size_t)prs_offset(outgoing_pdu),
1294 &auth_blob);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 data_blob_free(&auth_blob);
1297 return status;
1299 break;
1301 default:
1302 /* Can't happen. */
1303 smb_panic("bad auth level");
1304 /* Notreached. */
1305 return NT_STATUS_INVALID_PARAMETER;
1308 /* Finally marshall the blob. */
1310 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1311 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1312 (unsigned int)NTLMSSP_SIG_SIZE));
1313 data_blob_free(&auth_blob);
1314 return NT_STATUS_NO_MEMORY;
1317 data_blob_free(&auth_blob);
1318 return NT_STATUS_OK;
1321 /*******************************************************************
1322 Create and add the schannel sign/seal auth header and data.
1323 ********************************************************************/
1325 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1326 RPC_HDR *phdr,
1327 uint32 ss_padding_len,
1328 prs_struct *outgoing_pdu)
1330 RPC_HDR_AUTH auth_info;
1331 RPC_AUTH_SCHANNEL_CHK verf;
1332 struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
1333 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1334 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1336 if (!sas) {
1337 return NT_STATUS_INVALID_PARAMETER;
1340 /* Init and marshall the auth header. */
1341 init_rpc_hdr_auth(&auth_info,
1342 map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1343 cli->auth.auth_level,
1344 ss_padding_len,
1345 1 /* context id. */);
1347 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1348 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1349 return NT_STATUS_NO_MEMORY;
1352 switch (cli->auth.auth_level) {
1353 case PIPE_AUTH_LEVEL_PRIVACY:
1354 case PIPE_AUTH_LEVEL_INTEGRITY:
1355 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1356 sas->seq_num));
1358 schannel_encode(sas,
1359 cli->auth.auth_level,
1360 SENDER_IS_INITIATOR,
1361 &verf,
1362 data_p,
1363 data_and_pad_len);
1365 sas->seq_num++;
1366 break;
1368 default:
1369 /* Can't happen. */
1370 smb_panic("bad auth level");
1371 /* Notreached. */
1372 return NT_STATUS_INVALID_PARAMETER;
1375 /* Finally marshall the blob. */
1376 smb_io_rpc_auth_schannel_chk("",
1377 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1378 &verf,
1379 outgoing_pdu,
1382 return NT_STATUS_OK;
1385 /*******************************************************************
1386 Calculate how much data we're going to send in this packet, also
1387 work out any sign/seal padding length.
1388 ********************************************************************/
1390 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1391 uint32 data_left,
1392 uint16 *p_frag_len,
1393 uint16 *p_auth_len,
1394 uint32 *p_ss_padding)
1396 uint32 data_space, data_len;
1398 switch (cli->auth.auth_level) {
1399 case PIPE_AUTH_LEVEL_NONE:
1400 case PIPE_AUTH_LEVEL_CONNECT:
1401 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1402 data_len = MIN(data_space, data_left);
1403 *p_ss_padding = 0;
1404 *p_auth_len = 0;
1405 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1406 return data_len;
1408 case PIPE_AUTH_LEVEL_INTEGRITY:
1409 case PIPE_AUTH_LEVEL_PRIVACY:
1410 /* Treat the same for all authenticated rpc requests. */
1411 switch(cli->auth.auth_type) {
1412 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1413 case PIPE_AUTH_TYPE_NTLMSSP:
1414 *p_auth_len = NTLMSSP_SIG_SIZE;
1415 break;
1416 case PIPE_AUTH_TYPE_SCHANNEL:
1417 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1418 break;
1419 default:
1420 smb_panic("bad auth type");
1421 break;
1424 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1425 RPC_HDR_AUTH_LEN - *p_auth_len;
1427 data_len = MIN(data_space, data_left);
1428 if (data_len % 8) {
1429 *p_ss_padding = 8 - (data_len % 8);
1431 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1432 data_len + *p_ss_padding + /* data plus padding. */
1433 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1434 return data_len;
1436 default:
1437 smb_panic("bad auth level");
1438 /* Notreached. */
1439 return 0;
1443 /*******************************************************************
1444 External interface.
1445 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1446 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1447 and deals with signing/sealing details.
1448 ********************************************************************/
1450 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1451 uint8 op_num,
1452 prs_struct *in_data,
1453 prs_struct *out_data)
1455 NTSTATUS ret;
1456 uint32 data_left = prs_offset(in_data);
1457 uint32 alloc_hint = prs_offset(in_data);
1458 uint32 data_sent_thistime = 0;
1459 uint32 current_data_offset = 0;
1460 uint32 call_id = get_rpc_call_id();
1461 char pad[8];
1462 prs_struct outgoing_pdu;
1464 memset(pad, '\0', 8);
1466 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1467 /* Server is screwed up ! */
1468 return NT_STATUS_INVALID_PARAMETER;
1471 prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);
1473 while (1) {
1474 RPC_HDR hdr;
1475 RPC_HDR_REQ hdr_req;
1476 uint16 auth_len = 0;
1477 uint16 frag_len = 0;
1478 uint8 flags = 0;
1479 uint32 ss_padding = 0;
1481 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1482 &frag_len, &auth_len, &ss_padding);
1484 if (current_data_offset == 0) {
1485 flags = RPC_FLG_FIRST;
1488 if (data_sent_thistime == data_left) {
1489 flags |= RPC_FLG_LAST;
1492 /* Create and marshall the header and request header. */
1493 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1495 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1496 prs_mem_free(&outgoing_pdu);
1497 return NT_STATUS_NO_MEMORY;
1500 /* Create the rpc request RPC_HDR_REQ */
1501 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1503 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1504 prs_mem_free(&outgoing_pdu);
1505 return NT_STATUS_NO_MEMORY;
1508 /* Copy in the data, plus any ss padding. */
1509 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1510 prs_mem_free(&outgoing_pdu);
1511 return NT_STATUS_NO_MEMORY;
1514 /* Copy the sign/seal padding data. */
1515 if (ss_padding) {
1516 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1517 prs_mem_free(&outgoing_pdu);
1518 return NT_STATUS_NO_MEMORY;
1522 /* Generate any auth sign/seal and add the auth footer. */
1523 if (auth_len) {
1524 switch (cli->auth.auth_type) {
1525 case PIPE_AUTH_TYPE_NONE:
1526 break;
1527 case PIPE_AUTH_TYPE_NTLMSSP:
1528 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1529 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1530 if (!NT_STATUS_IS_OK(ret)) {
1531 prs_mem_free(&outgoing_pdu);
1532 return ret;
1534 break;
1535 case PIPE_AUTH_TYPE_SCHANNEL:
1536 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1537 if (!NT_STATUS_IS_OK(ret)) {
1538 prs_mem_free(&outgoing_pdu);
1539 return ret;
1541 break;
1542 default:
1543 smb_panic("bad auth type");
1544 break; /* notreached */
1548 /* Actually send the packet. */
1549 if (flags & RPC_FLG_LAST) {
1550 /* Last packet - send the data, get the reply and return. */
1551 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1552 prs_mem_free(&outgoing_pdu);
1554 if (DEBUGLEVEL >= 50) {
1555 char *dump_name = NULL;
1556 /* Also capture received data */
1557 if (asprintf(&dump_name, "%s/reply_%s_%d",
1558 get_dyn_LOGFILEBASE(), cli->pipe_name,
1559 op_num) > 0) {
1560 prs_dump(dump_name, op_num, out_data);
1561 SAFE_FREE(dump_name);
1565 return ret;
1566 } else {
1567 /* More packets to come - write and continue. */
1568 ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
1569 prs_data_p(&outgoing_pdu),
1570 (off_t)0,
1571 (size_t)hdr.frag_len);
1573 if (num_written != hdr.frag_len) {
1574 prs_mem_free(&outgoing_pdu);
1575 return cli_get_nt_error(cli->cli);
1579 current_data_offset += data_sent_thistime;
1580 data_left -= data_sent_thistime;
1582 /* Reset the marshalling position back to zero. */
1583 if (!prs_set_offset(&outgoing_pdu, 0)) {
1584 prs_mem_free(&outgoing_pdu);
1585 return NT_STATUS_NO_MEMORY;
1589 #if 0
1590 /****************************************************************************
1591 Set the handle state.
1592 ****************************************************************************/
1594 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1595 const char *pipe_name, uint16 device_state)
1597 bool state_set = False;
1598 char param[2];
1599 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1600 char *rparam = NULL;
1601 char *rdata = NULL;
1602 uint32 rparam_len, rdata_len;
1604 if (pipe_name == NULL)
1605 return False;
1607 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1608 cli->fnum, pipe_name, device_state));
1610 /* create parameters: device state */
1611 SSVAL(param, 0, device_state);
1613 /* create setup parameters. */
1614 setup[0] = 0x0001;
1615 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1617 /* send the data on \PIPE\ */
1618 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1619 setup, 2, 0, /* setup, length, max */
1620 param, 2, 0, /* param, length, max */
1621 NULL, 0, 1024, /* data, length, max */
1622 &rparam, &rparam_len, /* return param, length */
1623 &rdata, &rdata_len)) /* return data, length */
1625 DEBUG(5, ("Set Handle state: return OK\n"));
1626 state_set = True;
1629 SAFE_FREE(rparam);
1630 SAFE_FREE(rdata);
1632 return state_set;
1634 #endif
1636 /****************************************************************************
1637 Check the rpc bind acknowledge response.
1638 ****************************************************************************/
1640 static bool valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer)
1642 if ( pipe_idx >= PI_MAX_PIPES ) {
1643 DEBUG(0,("valid_pipe_name: Programmer error! Invalid pipe index [%d]\n",
1644 pipe_idx));
1645 return False;
1648 DEBUG(5,("Bind Abstract Syntax: "));
1649 dump_data(5, (uint8 *)&pipe_names[pipe_idx].abstr_syntax,
1650 sizeof(pipe_names[pipe_idx].abstr_syntax));
1651 DEBUG(5,("Bind Transfer Syntax: "));
1652 dump_data(5, (uint8 *)&pipe_names[pipe_idx].trans_syntax,
1653 sizeof(pipe_names[pipe_idx].trans_syntax));
1655 /* copy the required syntaxes out so we can do the right bind */
1657 *transfer = pipe_names[pipe_idx].trans_syntax;
1658 *abstract = pipe_names[pipe_idx].abstr_syntax;
1660 return True;
1663 /****************************************************************************
1664 Check the rpc bind acknowledge response.
1665 ****************************************************************************/
1667 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
1669 if ( hdr_ba->addr.len == 0) {
1670 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1673 # if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
1674 if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
1675 !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
1677 DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n",
1678 pipe_names[i].server_pipe ,hdr_ba->addr.str));
1679 return False;
1682 DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe ));
1684 if (pipe_names[pipe_idx].server_pipe == NULL) {
1685 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
1686 return False;
1688 #endif /* JERRY */
1690 /* check the transfer syntax */
1691 if ((hdr_ba->transfer.version != transfer->version) ||
1692 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1693 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1694 return False;
1697 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1698 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1699 hdr_ba->res.num_results, hdr_ba->res.reason));
1702 DEBUG(5,("check_bind_response: accepted!\n"));
1703 return True;
1706 /*******************************************************************
1707 Creates a DCE/RPC bind authentication response.
1708 This is the packet that is sent back to the server once we
1709 have received a BIND-ACK, to finish the third leg of
1710 the authentication handshake.
1711 ********************************************************************/
1713 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1714 uint32 rpc_call_id,
1715 enum pipe_auth_type auth_type,
1716 enum pipe_auth_level auth_level,
1717 DATA_BLOB *pauth_blob,
1718 prs_struct *rpc_out)
1720 RPC_HDR hdr;
1721 RPC_HDR_AUTH hdr_auth;
1722 uint32 pad = 0;
1724 /* Create the request RPC_HDR */
1725 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1726 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1727 pauth_blob->length );
1729 /* Marshall it. */
1730 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1731 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1732 return NT_STATUS_NO_MEMORY;
1736 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1737 about padding - shouldn't this pad to length 8 ? JRA.
1740 /* 4 bytes padding. */
1741 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1742 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1743 return NT_STATUS_NO_MEMORY;
1746 /* Create the request RPC_HDR_AUTHA */
1747 init_rpc_hdr_auth(&hdr_auth,
1748 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1749 auth_level, 0, 1);
1751 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1752 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1753 return NT_STATUS_NO_MEMORY;
1757 * Append the auth data to the outgoing buffer.
1760 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1761 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1762 return NT_STATUS_NO_MEMORY;
1765 return NT_STATUS_OK;
1768 /****************************************************************************
1769 Create and send the third packet in an RPC auth.
1770 ****************************************************************************/
1772 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1773 RPC_HDR *phdr,
1774 prs_struct *rbuf,
1775 uint32 rpc_call_id,
1776 enum pipe_auth_type auth_type,
1777 enum pipe_auth_level auth_level)
1779 DATA_BLOB server_response = data_blob_null;
1780 DATA_BLOB client_reply = data_blob_null;
1781 RPC_HDR_AUTH hdr_auth;
1782 NTSTATUS nt_status;
1783 prs_struct rpc_out;
1784 ssize_t ret;
1786 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1787 return NT_STATUS_INVALID_PARAMETER;
1790 /* Process the returned NTLMSSP blob first. */
1791 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1792 return NT_STATUS_INVALID_PARAMETER;
1795 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1796 return NT_STATUS_INVALID_PARAMETER;
1799 /* TODO - check auth_type/auth_level match. */
1801 server_response = data_blob(NULL, phdr->auth_len);
1802 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1804 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1805 server_response,
1806 &client_reply);
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1810 return nt_status;
1813 prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
1815 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1816 auth_type, auth_level,
1817 &client_reply, &rpc_out);
1819 if (!NT_STATUS_IS_OK(nt_status)) {
1820 prs_mem_free(&rpc_out);
1821 data_blob_free(&client_reply);
1822 data_blob_free(&server_response);
1823 return nt_status;
1826 /* 8 here is named pipe message mode. */
1827 ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
1828 (size_t)prs_offset(&rpc_out));
1830 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1831 DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
1832 prs_mem_free(&rpc_out);
1833 data_blob_free(&client_reply);
1834 data_blob_free(&server_response);
1835 return cli_get_nt_error(cli->cli);
1838 DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
1839 "fnum 0x%x sent auth3 response ok.\n",
1840 cli->cli->desthost,
1841 cli->pipe_name,
1842 (unsigned int)cli->fnum));
1844 prs_mem_free(&rpc_out);
1845 data_blob_free(&client_reply);
1846 data_blob_free(&server_response);
1847 return NT_STATUS_OK;
1850 /*******************************************************************
1851 Creates a DCE/RPC bind alter context authentication request which
1852 may contain a spnego auth blobl
1853 ********************************************************************/
1855 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
1856 RPC_IFACE *abstract,
1857 RPC_IFACE *transfer,
1858 enum pipe_auth_level auth_level,
1859 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1860 prs_struct *rpc_out)
1862 RPC_HDR_AUTH hdr_auth;
1863 prs_struct auth_info;
1864 NTSTATUS ret = NT_STATUS_OK;
1866 ZERO_STRUCT(hdr_auth);
1867 prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
1869 /* We may change the pad length before marshalling. */
1870 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1872 if (pauth_blob->length) {
1873 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
1874 prs_mem_free(&auth_info);
1875 return NT_STATUS_NO_MEMORY;
1879 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
1880 rpc_out,
1881 rpc_call_id,
1882 abstract,
1883 transfer,
1884 &hdr_auth,
1885 &auth_info);
1886 prs_mem_free(&auth_info);
1887 return ret;
1890 /*******************************************************************
1891 Third leg of the SPNEGO bind mechanism - sends alter context PDU
1892 and gets a response.
1893 ********************************************************************/
1895 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
1896 RPC_HDR *phdr,
1897 prs_struct *rbuf,
1898 uint32 rpc_call_id,
1899 RPC_IFACE *abstract,
1900 RPC_IFACE *transfer,
1901 enum pipe_auth_type auth_type,
1902 enum pipe_auth_level auth_level)
1904 DATA_BLOB server_spnego_response = data_blob_null;
1905 DATA_BLOB server_ntlm_response = data_blob_null;
1906 DATA_BLOB client_reply = data_blob_null;
1907 DATA_BLOB tmp_blob = data_blob_null;
1908 RPC_HDR_AUTH hdr_auth;
1909 NTSTATUS nt_status;
1910 prs_struct rpc_out;
1912 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1913 return NT_STATUS_INVALID_PARAMETER;
1916 /* Process the returned NTLMSSP blob first. */
1917 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1918 return NT_STATUS_INVALID_PARAMETER;
1921 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1922 return NT_STATUS_INVALID_PARAMETER;
1925 server_spnego_response = data_blob(NULL, phdr->auth_len);
1926 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1928 /* The server might give us back two challenges - tmp_blob is for the second. */
1929 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
1930 data_blob_free(&server_spnego_response);
1931 data_blob_free(&server_ntlm_response);
1932 data_blob_free(&tmp_blob);
1933 return NT_STATUS_INVALID_PARAMETER;
1936 /* We're finished with the server spnego response and the tmp_blob. */
1937 data_blob_free(&server_spnego_response);
1938 data_blob_free(&tmp_blob);
1940 nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1941 server_ntlm_response,
1942 &client_reply);
1944 /* Finished with the server_ntlm response */
1945 data_blob_free(&server_ntlm_response);
1947 if (!NT_STATUS_IS_OK(nt_status)) {
1948 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
1949 data_blob_free(&client_reply);
1950 return nt_status;
1953 /* SPNEGO wrap the client reply. */
1954 tmp_blob = spnego_gen_auth(client_reply);
1955 data_blob_free(&client_reply);
1956 client_reply = tmp_blob;
1957 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
1959 /* Now prepare the alter context pdu. */
1960 prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
1962 nt_status = create_rpc_alter_context(rpc_call_id,
1963 abstract,
1964 transfer,
1965 auth_level,
1966 &client_reply,
1967 &rpc_out);
1969 data_blob_free(&client_reply);
1971 if (!NT_STATUS_IS_OK(nt_status)) {
1972 prs_mem_free(&rpc_out);
1973 return nt_status;
1976 /* Initialize the returning data struct. */
1977 prs_mem_free(rbuf);
1978 prs_init(rbuf, 0, cli->mem_ctx, UNMARSHALL);
1980 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
1981 if (!NT_STATUS_IS_OK(nt_status)) {
1982 prs_mem_free(&rpc_out);
1983 return nt_status;
1986 prs_mem_free(&rpc_out);
1988 /* Get the auth blob from the reply. */
1989 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
1990 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
1991 return NT_STATUS_BUFFER_TOO_SMALL;
1994 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1995 return NT_STATUS_INVALID_PARAMETER;
1998 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1999 return NT_STATUS_INVALID_PARAMETER;
2002 server_spnego_response = data_blob(NULL, phdr->auth_len);
2003 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2005 /* Check we got a valid auth response. */
2006 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
2007 data_blob_free(&server_spnego_response);
2008 data_blob_free(&tmp_blob);
2009 return NT_STATUS_INVALID_PARAMETER;
2012 data_blob_free(&server_spnego_response);
2013 data_blob_free(&tmp_blob);
2015 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2016 "remote machine %s pipe %s fnum 0x%x.\n",
2017 cli->cli->desthost,
2018 cli->pipe_name,
2019 (unsigned int)cli->fnum));
2021 return NT_STATUS_OK;
2024 /****************************************************************************
2025 Do an rpc bind.
2026 ****************************************************************************/
2028 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2029 enum pipe_auth_type auth_type,
2030 enum pipe_auth_level auth_level)
2032 RPC_HDR hdr;
2033 RPC_HDR_BA hdr_ba;
2034 RPC_IFACE abstract;
2035 RPC_IFACE transfer;
2036 prs_struct rpc_out;
2037 prs_struct rbuf;
2038 uint32 rpc_call_id;
2039 NTSTATUS status;
2041 DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
2042 (unsigned int)cli->fnum,
2043 cli->pipe_name,
2044 (unsigned int)auth_type,
2045 (unsigned int)auth_level ));
2047 if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {
2048 return NT_STATUS_INVALID_PARAMETER;
2051 prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL);
2053 rpc_call_id = get_rpc_call_id();
2055 /* Marshall the outgoing data. */
2056 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2057 &abstract, &transfer,
2058 auth_type,
2059 auth_level);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 prs_mem_free(&rpc_out);
2063 return status;
2066 /* Initialize the incoming data struct. */
2067 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
2069 /* send data on \PIPE\. receive a response */
2070 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2071 if (!NT_STATUS_IS_OK(status)) {
2072 prs_mem_free(&rpc_out);
2073 return status;
2076 prs_mem_free(&rpc_out);
2078 DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
2079 "fnum 0x%x bind request returned ok.\n",
2080 cli->cli->desthost,
2081 cli->pipe_name,
2082 (unsigned int)cli->fnum));
2084 /* Unmarshall the RPC header */
2085 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2086 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2087 prs_mem_free(&rbuf);
2088 return NT_STATUS_BUFFER_TOO_SMALL;
2091 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2092 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2093 prs_mem_free(&rbuf);
2094 return NT_STATUS_BUFFER_TOO_SMALL;
2097 if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
2098 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2099 prs_mem_free(&rbuf);
2100 return NT_STATUS_BUFFER_TOO_SMALL;
2103 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2104 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2106 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2107 switch(auth_type) {
2109 case PIPE_AUTH_TYPE_NONE:
2110 case PIPE_AUTH_TYPE_SCHANNEL:
2111 /* Bind complete. */
2112 break;
2114 case PIPE_AUTH_TYPE_NTLMSSP:
2115 /* Need to send AUTH3 packet - no reply. */
2116 status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
2117 auth_type, auth_level);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 prs_mem_free(&rbuf);
2120 return status;
2122 break;
2124 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2125 /* Need to send alter context request and reply. */
2126 status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
2127 &abstract, &transfer,
2128 auth_type, auth_level);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 prs_mem_free(&rbuf);
2131 return status;
2133 break;
2135 case PIPE_AUTH_TYPE_KRB5:
2136 /* */
2138 default:
2139 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2140 (unsigned int)auth_type ));
2141 prs_mem_free(&rbuf);
2142 return NT_STATUS_INVALID_INFO_CLASS;
2145 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2146 if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2147 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2148 if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2149 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2150 prs_mem_free(&rbuf);
2151 return NT_STATUS_INVALID_PARAMETER;
2154 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2155 if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2156 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2157 prs_mem_free(&rbuf);
2158 return NT_STATUS_INVALID_PARAMETER;
2163 /* Pipe is bound - set up auth_type and auth_level data. */
2165 cli->auth.auth_type = auth_type;
2166 cli->auth.auth_level = auth_level;
2168 prs_mem_free(&rbuf);
2169 return NT_STATUS_OK;
2172 /****************************************************************************
2173 Open a named pipe over SMB to a remote server.
2175 * CAVEAT CALLER OF THIS FUNCTION:
2176 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2177 * so be sure that this function is called AFTER any structure (vs pointer)
2178 * assignment of the cli. In particular, libsmbclient does structure
2179 * assignments of cli, which invalidates the data in the returned
2180 * rpc_pipe_client if this function is called before the structure assignment
2181 * of cli.
2183 ****************************************************************************/
2185 static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2187 TALLOC_CTX *mem_ctx;
2188 struct rpc_pipe_client *result;
2189 int fnum;
2191 *perr = NT_STATUS_NO_MEMORY;
2193 /* sanity check to protect against crashes */
2195 if ( !cli ) {
2196 *perr = NT_STATUS_INVALID_HANDLE;
2197 return NULL;
2200 /* The pipe name index must fall within our array */
2201 SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
2203 mem_ctx = talloc_init("struct rpc_pipe_client");
2204 if (mem_ctx == NULL) {
2205 return NULL;
2208 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2209 if (result == NULL) {
2210 return NULL;
2213 result->mem_ctx = mem_ctx;
2215 result->pipe_name = cli_get_pipe_name(pipe_idx);
2217 fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
2219 if (fnum == -1) {
2220 DEBUG(1,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
2221 "to machine %s. Error was %s\n",
2222 result->pipe_name, cli->desthost,
2223 cli_errstr(cli)));
2224 *perr = cli_get_nt_error(cli);
2225 talloc_destroy(result->mem_ctx);
2226 return NULL;
2229 result->fnum = fnum;
2230 result->cli = cli;
2231 result->pipe_idx = pipe_idx;
2232 result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
2233 result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
2235 if (pipe_idx == PI_NETLOGON) {
2236 /* Set up a netlogon credential chain for a netlogon pipe. */
2237 result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
2238 if (result->dc == NULL) {
2239 talloc_destroy(result->mem_ctx);
2240 return NULL;
2244 DLIST_ADD(cli->pipe_list, result);
2245 *perr = NT_STATUS_OK;
2247 return result;
2250 /****************************************************************************
2251 Open a named pipe to an SMB server and bind anonymously.
2252 ****************************************************************************/
2254 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2256 struct rpc_pipe_client *result;
2258 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2259 if (result == NULL) {
2260 return NULL;
2263 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
2264 if (!NT_STATUS_IS_OK(*perr)) {
2265 int lvl = 0;
2266 if (pipe_idx == PI_LSARPC_DS) {
2267 /* non AD domains just don't have this pipe, avoid
2268 * level 0 statement in that case - gd */
2269 lvl = 3;
2271 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
2272 cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
2273 cli_rpc_pipe_close(result);
2274 return NULL;
2277 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
2278 result->pipe_name, cli->desthost ));
2280 return result;
2283 /****************************************************************************
2284 Free function for NTLMSSP auth.
2285 ****************************************************************************/
2287 static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
2289 if (auth->a_u.ntlmssp_state) {
2290 ntlmssp_end(&auth->a_u.ntlmssp_state);
2291 auth->a_u.ntlmssp_state = NULL;
2295 /****************************************************************************
2296 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2297 ****************************************************************************/
2299 static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
2300 int pipe_idx,
2301 enum pipe_auth_type auth_type,
2302 enum pipe_auth_level auth_level,
2303 const char *domain,
2304 const char *username,
2305 const char *password,
2306 NTSTATUS *perr)
2308 struct rpc_pipe_client *result;
2309 NTLMSSP_STATE *ntlmssp_state = NULL;
2311 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2312 if (result == NULL) {
2313 return NULL;
2316 result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
2318 result->domain = domain;
2319 result->user_name = username;
2320 pwd_set_cleartext(&result->pwd, password);
2322 *perr = ntlmssp_client_start(&ntlmssp_state);
2323 if (!NT_STATUS_IS_OK(*perr)) {
2324 goto err;
2327 result->auth.a_u.ntlmssp_state = ntlmssp_state;
2329 *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name);
2330 if (!NT_STATUS_IS_OK(*perr)) {
2331 goto err;
2334 *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain);
2335 if (!NT_STATUS_IS_OK(*perr)) {
2336 goto err;
2339 if (cli->pwd.null_pwd) {
2340 *perr = ntlmssp_set_password(ntlmssp_state, NULL);
2341 if (!NT_STATUS_IS_OK(*perr)) {
2342 goto err;
2344 } else {
2345 *perr = ntlmssp_set_password(ntlmssp_state, password);
2346 if (!NT_STATUS_IS_OK(*perr)) {
2347 goto err;
2351 /* Turn off sign+seal to allow selected auth level to turn it back on. */
2352 ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
2354 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2355 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2356 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2357 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2360 *perr = rpc_pipe_bind(result, auth_type, auth_level);
2361 if (!NT_STATUS_IS_OK(*perr)) {
2362 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2363 nt_errstr(*perr) ));
2364 goto err;
2367 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2368 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2369 result->pipe_name, cli->desthost,
2370 domain, username ));
2372 return result;
2374 err:
2376 cli_rpc_pipe_close(result);
2377 return NULL;
2380 /****************************************************************************
2381 External interface.
2382 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
2383 ****************************************************************************/
2385 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2386 int pipe_idx,
2387 enum pipe_auth_level auth_level,
2388 const char *domain,
2389 const char *username,
2390 const char *password,
2391 NTSTATUS *perr)
2393 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2394 pipe_idx,
2395 PIPE_AUTH_TYPE_NTLMSSP,
2396 auth_level,
2397 domain,
2398 username,
2399 password,
2400 perr);
2403 /****************************************************************************
2404 External interface.
2405 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
2406 ****************************************************************************/
2408 struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
2409 int pipe_idx,
2410 enum pipe_auth_level auth_level,
2411 const char *domain,
2412 const char *username,
2413 const char *password,
2414 NTSTATUS *perr)
2416 return cli_rpc_pipe_open_ntlmssp_internal(cli,
2417 pipe_idx,
2418 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
2419 auth_level,
2420 domain,
2421 username,
2422 password,
2423 perr);
2426 /****************************************************************************
2427 Get a the schannel session key out of an already opened netlogon pipe.
2428 ****************************************************************************/
2429 static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2430 struct cli_state *cli,
2431 const char *domain,
2432 uint32 *pneg_flags,
2433 NTSTATUS *perr)
2435 uint32 sec_chan_type = 0;
2436 unsigned char machine_pwd[16];
2437 const char *machine_account;
2439 /* Get the machine account credentials from secrets.tdb. */
2440 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2441 &sec_chan_type))
2443 DEBUG(0, ("get_schannel_session_key: could not fetch "
2444 "trust account password for domain '%s'\n",
2445 domain));
2446 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2447 return false;
2450 *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
2451 cli->desthost, /* server name */
2452 domain, /* domain */
2453 global_myname(), /* client name */
2454 machine_account, /* machine account name */
2455 machine_pwd,
2456 sec_chan_type,
2457 pneg_flags);
2459 if (!NT_STATUS_IS_OK(*perr)) {
2460 DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
2461 "failed with result %s to server %s, domain %s, machine account %s.\n",
2462 nt_errstr(*perr), cli->desthost, domain, machine_account ));
2463 return false;
2466 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
2467 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2468 cli->desthost));
2469 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
2470 return false;
2473 return true;
2476 /****************************************************************************
2477 Open a netlogon pipe and get the schannel session key.
2478 Now exposed to external callers.
2479 ****************************************************************************/
2482 struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
2483 const char *domain,
2484 uint32 *pneg_flags,
2485 NTSTATUS *perr)
2487 struct rpc_pipe_client *netlogon_pipe = NULL;
2489 netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
2490 if (!netlogon_pipe) {
2491 return NULL;
2494 if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2495 pneg_flags, perr))
2497 cli_rpc_pipe_close(netlogon_pipe);
2498 return NULL;
2501 return netlogon_pipe;
2504 /****************************************************************************
2505 External interface.
2506 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2507 using session_key. sign and seal.
2508 ****************************************************************************/
2510 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2511 int pipe_idx,
2512 enum pipe_auth_level auth_level,
2513 const char *domain,
2514 const struct dcinfo *pdc,
2515 NTSTATUS *perr)
2517 struct rpc_pipe_client *result;
2519 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2520 if (result == NULL) {
2521 return NULL;
2524 result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct);
2525 if (!result->auth.a_u.schannel_auth) {
2526 cli_rpc_pipe_close(result);
2527 *perr = NT_STATUS_NO_MEMORY;
2528 return NULL;
2531 result->domain = domain;
2532 memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
2534 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
2535 if (!NT_STATUS_IS_OK(*perr)) {
2536 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
2537 nt_errstr(*perr) ));
2538 cli_rpc_pipe_close(result);
2539 return NULL;
2542 /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
2543 if (result->dc) {
2544 *result->dc = *pdc;
2547 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2548 "for domain %s "
2549 "and bound using schannel.\n",
2550 result->pipe_name, cli->desthost, domain ));
2552 return result;
2555 /****************************************************************************
2556 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2557 Fetch the session key ourselves using a temporary netlogon pipe. This
2558 version uses an ntlmssp auth bound netlogon pipe to get the key.
2559 ****************************************************************************/
2561 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
2562 const char *domain,
2563 const char *username,
2564 const char *password,
2565 uint32 *pneg_flags,
2566 NTSTATUS *perr)
2568 struct rpc_pipe_client *netlogon_pipe = NULL;
2570 netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
2571 if (!netlogon_pipe) {
2572 return NULL;
2575 if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2576 pneg_flags, perr))
2578 cli_rpc_pipe_close(netlogon_pipe);
2579 return NULL;
2582 return netlogon_pipe;
2585 /****************************************************************************
2586 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2587 Fetch the session key ourselves using a temporary netlogon pipe. This version
2588 uses an ntlmssp bind to get the session key.
2589 ****************************************************************************/
2591 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
2592 int pipe_idx,
2593 enum pipe_auth_level auth_level,
2594 const char *domain,
2595 const char *username,
2596 const char *password,
2597 NTSTATUS *perr)
2599 uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
2600 struct rpc_pipe_client *netlogon_pipe = NULL;
2601 struct rpc_pipe_client *result = NULL;
2603 netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
2604 password, &neg_flags, perr);
2605 if (!netlogon_pipe) {
2606 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
2607 "key from server %s for domain %s.\n",
2608 cli->desthost, domain ));
2609 return NULL;
2612 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2613 auth_level,
2614 domain, netlogon_pipe->dc, perr);
2616 /* Now we've bound using the session key we can close the netlog pipe. */
2617 cli_rpc_pipe_close(netlogon_pipe);
2619 return result;
2622 /****************************************************************************
2623 Open a named pipe to an SMB server and bind using schannel (bind type 68).
2624 Fetch the session key ourselves using a temporary netlogon pipe.
2625 ****************************************************************************/
2627 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
2628 int pipe_idx,
2629 enum pipe_auth_level auth_level,
2630 const char *domain,
2631 NTSTATUS *perr)
2633 uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
2634 struct rpc_pipe_client *netlogon_pipe = NULL;
2635 struct rpc_pipe_client *result = NULL;
2637 netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
2638 if (!netlogon_pipe) {
2639 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
2640 "key from server %s for domain %s.\n",
2641 cli->desthost, domain ));
2642 return NULL;
2645 result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2646 auth_level,
2647 domain, netlogon_pipe->dc, perr);
2649 /* Now we've bound using the session key we can close the netlog pipe. */
2650 cli_rpc_pipe_close(netlogon_pipe);
2652 return result;
2655 #ifdef HAVE_KRB5
2657 /****************************************************************************
2658 Free function for the kerberos spcific data.
2659 ****************************************************************************/
2661 static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
2663 data_blob_free(&a->a_u.kerberos_auth->session_key);
2666 #endif
2668 /****************************************************************************
2669 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
2670 The idea is this can be called with service_princ, username and password all
2671 NULL so long as the caller has a TGT.
2672 ****************************************************************************/
2674 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
2675 int pipe_idx,
2676 enum pipe_auth_level auth_level,
2677 const char *service_princ,
2678 const char *username,
2679 const char *password,
2680 NTSTATUS *perr)
2682 #ifdef HAVE_KRB5
2683 struct rpc_pipe_client *result;
2685 result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2686 if (result == NULL) {
2687 return NULL;
2690 /* Default service principal is "desthost$@realm" */
2691 if (!service_princ) {
2692 service_princ = talloc_asprintf(result->mem_ctx, "%s$@%s",
2693 cli->desthost, lp_realm() );
2694 if (!service_princ) {
2695 cli_rpc_pipe_close(result);
2696 return NULL;
2700 /* Only get a new TGT if username/password are given. */
2701 if (username && password) {
2702 int ret = kerberos_kinit_password(username, password, 0, NULL);
2703 if (ret) {
2704 cli_rpc_pipe_close(result);
2705 return NULL;
2709 result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(result->mem_ctx, struct kerberos_auth_struct);
2710 if (!result->auth.a_u.kerberos_auth) {
2711 cli_rpc_pipe_close(result);
2712 *perr = NT_STATUS_NO_MEMORY;
2713 return NULL;
2716 result->auth.a_u.kerberos_auth->service_principal = service_princ;
2717 result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
2719 *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
2720 if (!NT_STATUS_IS_OK(*perr)) {
2721 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
2722 nt_errstr(*perr) ));
2723 cli_rpc_pipe_close(result);
2724 return NULL;
2727 return result;
2728 #else
2729 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
2730 return NULL;
2731 #endif