Remove now unused cli_get_pipe_idx
[Samba/gebeck_regimport.git] / source / rpc_client / cli_pipe.c
blob3f27a89fc40ae650d54cfb15394d40cab5add910
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Largely rewritten by Jeremy Allison 2005.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_CLI
26 /*******************************************************************
27 interface/version dce/rpc pipe identification
28 ********************************************************************/
30 #define PIPE_SRVSVC "\\PIPE\\srvsvc"
31 #define PIPE_SAMR "\\PIPE\\samr"
32 #define PIPE_WINREG "\\PIPE\\winreg"
33 #define PIPE_WKSSVC "\\PIPE\\wkssvc"
34 #define PIPE_NETLOGON "\\PIPE\\NETLOGON"
35 #define PIPE_NTLSA "\\PIPE\\ntlsa"
36 #define PIPE_NTSVCS "\\PIPE\\ntsvcs"
37 #define PIPE_LSASS "\\PIPE\\lsass"
38 #define PIPE_LSARPC "\\PIPE\\lsarpc"
39 #define PIPE_SPOOLSS "\\PIPE\\spoolss"
40 #define PIPE_NETDFS "\\PIPE\\netdfs"
41 #define PIPE_ECHO "\\PIPE\\rpcecho"
42 #define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
43 #define PIPE_EPM "\\PIPE\\epmapper"
44 #define PIPE_SVCCTL "\\PIPE\\svcctl"
45 #define PIPE_EVENTLOG "\\PIPE\\eventlog"
46 #define PIPE_EPMAPPER "\\PIPE\\epmapper"
47 #define PIPE_DRSUAPI "\\PIPE\\drsuapi"
50 * IMPORTANT!! If you update this structure, make sure to
51 * update the index #defines in smb.h.
54 static const struct pipe_id_info {
55 /* the names appear not to matter: the syntaxes _do_ matter */
57 const char *client_pipe;
58 const RPC_IFACE *abstr_syntax; /* this one is the abstract syntax id */
59 } pipe_names [] =
61 { PIPE_LSARPC, &ndr_table_lsarpc.syntax_id },
62 { PIPE_LSARPC, &ndr_table_dssetup.syntax_id },
63 { PIPE_SAMR, &ndr_table_samr.syntax_id },
64 { PIPE_NETLOGON, &ndr_table_netlogon.syntax_id },
65 { PIPE_SRVSVC, &ndr_table_srvsvc.syntax_id },
66 { PIPE_WKSSVC, &ndr_table_wkssvc.syntax_id },
67 { PIPE_WINREG, &ndr_table_winreg.syntax_id },
68 { PIPE_SPOOLSS, &syntax_spoolss },
69 { PIPE_NETDFS, &ndr_table_netdfs.syntax_id },
70 { PIPE_ECHO, &ndr_table_rpcecho.syntax_id },
71 { PIPE_SHUTDOWN, &ndr_table_initshutdown.syntax_id },
72 { PIPE_SVCCTL, &ndr_table_svcctl.syntax_id },
73 { PIPE_EVENTLOG, &ndr_table_eventlog.syntax_id },
74 { PIPE_NTSVCS, &ndr_table_ntsvcs.syntax_id },
75 { PIPE_EPMAPPER, &ndr_table_epmapper.syntax_id },
76 { PIPE_DRSUAPI, &ndr_table_drsuapi.syntax_id },
77 { NULL, NULL }
80 /****************************************************************************
81 Return the pipe name from the index.
82 ****************************************************************************/
84 const char *cli_get_pipe_name(int pipe_idx)
86 return &pipe_names[pipe_idx].client_pipe[5];
89 const char *cli_get_pipe_name_from_iface(TALLOC_CTX *mem_ctx,
90 struct cli_state *cli,
91 const struct ndr_syntax_id *interface)
93 int i;
94 for (i = 0; pipe_names[i].client_pipe; i++) {
95 if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
96 interface)) {
97 return cli_get_pipe_name(i);
102 * Here we should ask \\epmapper, but for now our code is only
103 * interested in the known pipes mentioned in pipe_names[]
106 return NULL;
109 /********************************************************************
110 Map internal value to wire value.
111 ********************************************************************/
113 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
115 switch (auth_type) {
117 case PIPE_AUTH_TYPE_NONE:
118 return RPC_ANONYMOUS_AUTH_TYPE;
120 case PIPE_AUTH_TYPE_NTLMSSP:
121 return RPC_NTLMSSP_AUTH_TYPE;
123 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
124 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
125 return RPC_SPNEGO_AUTH_TYPE;
127 case PIPE_AUTH_TYPE_SCHANNEL:
128 return RPC_SCHANNEL_AUTH_TYPE;
130 case PIPE_AUTH_TYPE_KRB5:
131 return RPC_KRB5_AUTH_TYPE;
133 default:
134 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
135 "auth type %u\n",
136 (unsigned int)auth_type ));
137 break;
139 return -1;
142 /********************************************************************
143 Pipe description for a DEBUG
144 ********************************************************************/
145 static char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli)
147 char *result;
149 switch (cli->transport_type) {
150 case NCACN_NP:
151 result = talloc_asprintf(mem_ctx, "host %s, pipe %s, "
152 "fnum 0x%x",
153 cli->desthost,
154 cli->trans.np.pipe_name,
155 (unsigned int)(cli->trans.np.fnum));
156 break;
157 case NCACN_IP_TCP:
158 case NCACN_UNIX_STREAM:
159 result = talloc_asprintf(mem_ctx, "host %s, fd %d",
160 cli->desthost, cli->trans.sock.fd);
161 break;
162 default:
163 result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
164 break;
166 SMB_ASSERT(result != NULL);
167 return result;
170 /********************************************************************
171 Rpc pipe call id.
172 ********************************************************************/
174 static uint32 get_rpc_call_id(void)
176 static uint32 call_id = 0;
177 return ++call_id;
180 /*******************************************************************
181 Read from a RPC named pipe
182 ********************************************************************/
183 static NTSTATUS rpc_read_np(struct cli_state *cli, const char *pipe_name,
184 int fnum, char *buf, off_t offset, size_t size,
185 ssize_t *pnum_read)
187 ssize_t num_read;
189 num_read = cli_read(cli, fnum, buf, offset, size);
191 DEBUG(5,("rpc_read_np: num_read = %d, read offset: %u, to read: %u\n",
192 (int)num_read, (unsigned int)offset, (unsigned int)size));
195 * A dos error of ERRDOS/ERRmoredata is not an error.
197 if (cli_is_dos_error(cli)) {
198 uint32 ecode;
199 uint8 eclass;
200 cli_dos_error(cli, &eclass, &ecode);
201 if (eclass != ERRDOS && ecode != ERRmoredata) {
202 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read "
203 "on fnum 0x%x\n", eclass, (unsigned int)ecode,
204 cli_errstr(cli), fnum));
205 return dos_to_ntstatus(eclass, ecode);
210 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
212 if (cli_is_nt_error(cli)) {
213 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
214 NT_STATUS_BUFFER_TOO_SMALL)) {
215 DEBUG(0,("rpc_read: Error (%s) in cli_read on fnum "
216 "0x%x\n", nt_errstr(cli_nt_error(cli)), fnum));
217 return cli_nt_error(cli);
221 if (num_read == -1) {
222 DEBUG(0,("rpc_read: Error - cli_read on fnum 0x%x returned "
223 "-1\n", fnum));
224 return cli_get_nt_error(cli);
227 *pnum_read = num_read;
228 return NT_STATUS_OK;
232 /*******************************************************************
233 Use SMBreadX to get rest of one fragment's worth of rpc data.
234 Will expand the current_pdu struct to the correct size.
235 ********************************************************************/
237 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
238 prs_struct *current_pdu,
239 uint32 data_to_read,
240 uint32 *current_pdu_offset)
242 size_t size = (size_t)cli->max_recv_frag;
243 uint32 stream_offset = 0;
244 ssize_t num_read = 0;
245 char *pdata;
246 ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
248 DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
249 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
252 * Grow the buffer if needed to accommodate the data to be read.
255 if (extra_data_size > 0) {
256 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
257 DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
258 return NT_STATUS_NO_MEMORY;
260 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
263 pdata = prs_data_p(current_pdu) + *current_pdu_offset;
265 do {
266 NTSTATUS status;
268 /* read data using SMBreadX */
269 if (size > (size_t)data_to_read) {
270 size = (size_t)data_to_read;
273 switch (cli->transport_type) {
274 case NCACN_NP:
275 status = rpc_read_np(cli->trans.np.cli,
276 cli->trans.np.pipe_name,
277 cli->trans.np.fnum, pdata,
278 (off_t)stream_offset, size,
279 &num_read);
280 break;
281 case NCACN_IP_TCP:
282 case NCACN_UNIX_STREAM:
283 status = NT_STATUS_OK;
284 num_read = sys_read(cli->trans.sock.fd, pdata, size);
285 if (num_read == -1) {
286 status = map_nt_error_from_unix(errno);
288 if (num_read == 0) {
289 status = NT_STATUS_END_OF_FILE;
291 break;
292 default:
293 DEBUG(0, ("unknown transport type %d\n",
294 cli->transport_type));
295 return NT_STATUS_INTERNAL_ERROR;
298 data_to_read -= num_read;
299 stream_offset += num_read;
300 pdata += num_read;
302 } while (num_read > 0 && data_to_read > 0);
303 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
306 * Update the current offset into current_pdu by the amount read.
308 *current_pdu_offset += stream_offset;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Try and get a PDU's worth of data from current_pdu. If not, then read more
314 from the wire.
315 ****************************************************************************/
317 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
319 NTSTATUS ret = NT_STATUS_OK;
320 uint32 current_pdu_len = prs_data_size(current_pdu);
322 /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
323 if (current_pdu_len < RPC_HEADER_LEN) {
324 /* rpc_read expands the current_pdu struct as neccessary. */
325 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
326 if (!NT_STATUS_IS_OK(ret)) {
327 return ret;
331 /* This next call sets the endian bit correctly in current_pdu. */
332 /* We will propagate this to rbuf later. */
333 if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) {
334 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
335 return NT_STATUS_BUFFER_TOO_SMALL;
338 /* Ensure we have frag_len bytes of data. */
339 if (current_pdu_len < prhdr->frag_len) {
340 /* rpc_read expands the current_pdu struct as neccessary. */
341 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
342 if (!NT_STATUS_IS_OK(ret)) {
343 return ret;
347 if (current_pdu_len < prhdr->frag_len) {
348 return NT_STATUS_BUFFER_TOO_SMALL;
351 return NT_STATUS_OK;
354 /****************************************************************************
355 NTLMSSP specific sign/seal.
356 Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
357 In fact I should probably abstract these into identical pieces of code... JRA.
358 ****************************************************************************/
360 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
361 prs_struct *current_pdu,
362 uint8 *p_ss_padding_len)
364 RPC_HDR_AUTH auth_info;
365 uint32 save_offset = prs_offset(current_pdu);
366 uint32 auth_len = prhdr->auth_len;
367 NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
368 unsigned char *data = NULL;
369 size_t data_len;
370 unsigned char *full_packet_data = NULL;
371 size_t full_packet_data_len;
372 DATA_BLOB auth_blob;
373 NTSTATUS status;
375 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
376 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
377 return NT_STATUS_OK;
380 if (!ntlmssp_state) {
381 return NT_STATUS_INVALID_PARAMETER;
384 /* Ensure there's enough data for an authenticated response. */
385 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
386 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
387 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
388 (unsigned int)auth_len ));
389 return NT_STATUS_BUFFER_TOO_SMALL;
393 * We need the full packet data + length (minus auth stuff) as well as the packet data + length
394 * after the RPC header.
395 * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
396 * functions as NTLMv2 checks the rpc headers also.
399 data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
400 data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
402 full_packet_data = (unsigned char *)prs_data_p(current_pdu);
403 full_packet_data_len = prhdr->frag_len - auth_len;
405 /* Pull the auth header and the following data into a blob. */
406 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
407 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
408 (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
409 return NT_STATUS_BUFFER_TOO_SMALL;
412 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
413 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
414 return NT_STATUS_BUFFER_TOO_SMALL;
417 auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
418 auth_blob.length = auth_len;
420 switch (cli->auth->auth_level) {
421 case PIPE_AUTH_LEVEL_PRIVACY:
422 /* Data is encrypted. */
423 status = ntlmssp_unseal_packet(ntlmssp_state,
424 data, data_len,
425 full_packet_data,
426 full_packet_data_len,
427 &auth_blob);
428 if (!NT_STATUS_IS_OK(status)) {
429 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
430 "packet from %s. Error was %s.\n",
431 rpccli_pipe_txt(debug_ctx(), cli),
432 nt_errstr(status) ));
433 return status;
435 break;
436 case PIPE_AUTH_LEVEL_INTEGRITY:
437 /* Data is signed. */
438 status = ntlmssp_check_packet(ntlmssp_state,
439 data, data_len,
440 full_packet_data,
441 full_packet_data_len,
442 &auth_blob);
443 if (!NT_STATUS_IS_OK(status)) {
444 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
445 "packet from %s. Error was %s.\n",
446 rpccli_pipe_txt(debug_ctx(), cli),
447 nt_errstr(status) ));
448 return status;
450 break;
451 default:
452 DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
453 "auth level %d\n", cli->auth->auth_level));
454 return NT_STATUS_INVALID_INFO_CLASS;
458 * Return the current pointer to the data offset.
461 if(!prs_set_offset(current_pdu, save_offset)) {
462 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
463 (unsigned int)save_offset ));
464 return NT_STATUS_BUFFER_TOO_SMALL;
468 * Remember the padding length. We must remove it from the real data
469 * stream once the sign/seal is done.
472 *p_ss_padding_len = auth_info.auth_pad_len;
474 return NT_STATUS_OK;
477 /****************************************************************************
478 schannel specific sign/seal.
479 ****************************************************************************/
481 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
482 prs_struct *current_pdu,
483 uint8 *p_ss_padding_len)
485 RPC_HDR_AUTH auth_info;
486 RPC_AUTH_SCHANNEL_CHK schannel_chk;
487 uint32 auth_len = prhdr->auth_len;
488 uint32 save_offset = prs_offset(current_pdu);
489 struct schannel_auth_struct *schannel_auth =
490 cli->auth->a_u.schannel_auth;
491 uint32 data_len;
493 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_NONE
494 || cli->auth->auth_level == PIPE_AUTH_LEVEL_CONNECT) {
495 return NT_STATUS_OK;
498 if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
499 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
500 return NT_STATUS_INVALID_PARAMETER;
503 if (!schannel_auth) {
504 return NT_STATUS_INVALID_PARAMETER;
507 /* Ensure there's enough data for an authenticated response. */
508 if ((auth_len > RPC_MAX_SIGN_SIZE) ||
509 (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
510 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
511 (unsigned int)auth_len ));
512 return NT_STATUS_INVALID_PARAMETER;
515 data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
517 if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
518 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
519 (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
520 return NT_STATUS_BUFFER_TOO_SMALL;
523 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
524 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
525 return NT_STATUS_BUFFER_TOO_SMALL;
528 if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
529 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
530 auth_info.auth_type));
531 return NT_STATUS_BUFFER_TOO_SMALL;
534 if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
535 &schannel_chk, current_pdu, 0)) {
536 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
537 return NT_STATUS_BUFFER_TOO_SMALL;
540 if (!schannel_decode(schannel_auth,
541 cli->auth->auth_level,
542 SENDER_IS_ACCEPTOR,
543 &schannel_chk,
544 prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
545 data_len)) {
546 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
547 "Connection to %s.\n",
548 rpccli_pipe_txt(debug_ctx(), cli)));
549 return NT_STATUS_INVALID_PARAMETER;
552 /* The sequence number gets incremented on both send and receive. */
553 schannel_auth->seq_num++;
556 * Return the current pointer to the data offset.
559 if(!prs_set_offset(current_pdu, save_offset)) {
560 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
561 (unsigned int)save_offset ));
562 return NT_STATUS_BUFFER_TOO_SMALL;
566 * Remember the padding length. We must remove it from the real data
567 * stream once the sign/seal is done.
570 *p_ss_padding_len = auth_info.auth_pad_len;
572 return NT_STATUS_OK;
575 /****************************************************************************
576 Do the authentication checks on an incoming pdu. Check sign and unseal etc.
577 ****************************************************************************/
579 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
580 prs_struct *current_pdu,
581 uint8 *p_ss_padding_len)
583 NTSTATUS ret = NT_STATUS_OK;
585 /* Paranioa checks for auth_len. */
586 if (prhdr->auth_len) {
587 if (prhdr->auth_len > prhdr->frag_len) {
588 return NT_STATUS_INVALID_PARAMETER;
591 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
592 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
593 /* Integer wrap attempt. */
594 return NT_STATUS_INVALID_PARAMETER;
599 * Now we have a complete RPC request PDU fragment, try and verify any auth data.
602 switch(cli->auth->auth_type) {
603 case PIPE_AUTH_TYPE_NONE:
604 if (prhdr->auth_len) {
605 DEBUG(3, ("cli_pipe_validate_rpc_response: "
606 "Connection to %s - got non-zero "
607 "auth len %u.\n",
608 rpccli_pipe_txt(debug_ctx(), cli),
609 (unsigned int)prhdr->auth_len ));
610 return NT_STATUS_INVALID_PARAMETER;
612 break;
614 case PIPE_AUTH_TYPE_NTLMSSP:
615 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
616 ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
617 if (!NT_STATUS_IS_OK(ret)) {
618 return ret;
620 break;
622 case PIPE_AUTH_TYPE_SCHANNEL:
623 ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
624 if (!NT_STATUS_IS_OK(ret)) {
625 return ret;
627 break;
629 case PIPE_AUTH_TYPE_KRB5:
630 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
631 default:
632 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
633 "to %s - unknown internal auth type %u.\n",
634 rpccli_pipe_txt(debug_ctx(), cli),
635 cli->auth->auth_type ));
636 return NT_STATUS_INVALID_INFO_CLASS;
639 return NT_STATUS_OK;
642 /****************************************************************************
643 Do basic authentication checks on an incoming pdu.
644 ****************************************************************************/
646 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
647 prs_struct *current_pdu,
648 uint8 expected_pkt_type,
649 char **ppdata,
650 uint32 *pdata_len,
651 prs_struct *return_data)
654 NTSTATUS ret = NT_STATUS_OK;
655 uint32 current_pdu_len = prs_data_size(current_pdu);
657 if (current_pdu_len != prhdr->frag_len) {
658 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
659 (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
660 return NT_STATUS_INVALID_PARAMETER;
664 * Point the return values at the real data including the RPC
665 * header. Just in case the caller wants it.
667 *ppdata = prs_data_p(current_pdu);
668 *pdata_len = current_pdu_len;
670 /* Ensure we have the correct type. */
671 switch (prhdr->pkt_type) {
672 case RPC_ALTCONTRESP:
673 case RPC_BINDACK:
675 /* Alter context and bind ack share the same packet definitions. */
676 break;
679 case RPC_RESPONSE:
681 RPC_HDR_RESP rhdr_resp;
682 uint8 ss_padding_len = 0;
684 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
685 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
686 return NT_STATUS_BUFFER_TOO_SMALL;
689 /* Here's where we deal with incoming sign/seal. */
690 ret = cli_pipe_validate_rpc_response(cli, prhdr,
691 current_pdu, &ss_padding_len);
692 if (!NT_STATUS_IS_OK(ret)) {
693 return ret;
696 /* Point the return values at the NDR data. Remember to remove any ss padding. */
697 *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
699 if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
700 return NT_STATUS_BUFFER_TOO_SMALL;
703 *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
705 /* Remember to remove the auth footer. */
706 if (prhdr->auth_len) {
707 /* We've already done integer wrap tests on auth_len in
708 cli_pipe_validate_rpc_response(). */
709 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
710 return NT_STATUS_BUFFER_TOO_SMALL;
712 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
715 DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
716 current_pdu_len, *pdata_len, ss_padding_len ));
719 * If this is the first reply, and the allocation hint is reasonably, try and
720 * set up the return_data parse_struct to the correct size.
723 if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
724 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
725 DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
726 "too large to allocate\n",
727 (unsigned int)rhdr_resp.alloc_hint ));
728 return NT_STATUS_NO_MEMORY;
732 break;
735 case RPC_BINDNACK:
736 DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
737 "received from %s!\n",
738 rpccli_pipe_txt(debug_ctx(), cli)));
739 /* Use this for now... */
740 return NT_STATUS_NETWORK_ACCESS_DENIED;
742 case RPC_FAULT:
744 RPC_HDR_RESP rhdr_resp;
745 RPC_HDR_FAULT fault_resp;
747 if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
748 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
749 return NT_STATUS_BUFFER_TOO_SMALL;
752 if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
753 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
754 return NT_STATUS_BUFFER_TOO_SMALL;
757 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
758 "code %s received from %s!\n",
759 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
760 rpccli_pipe_txt(debug_ctx(), cli)));
761 if (NT_STATUS_IS_OK(fault_resp.status)) {
762 return NT_STATUS_UNSUCCESSFUL;
763 } else {
764 return fault_resp.status;
768 default:
769 DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
770 "from %s!\n",
771 (unsigned int)prhdr->pkt_type,
772 rpccli_pipe_txt(debug_ctx(), cli)));
773 return NT_STATUS_INVALID_INFO_CLASS;
776 if (prhdr->pkt_type != expected_pkt_type) {
777 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
778 "got an unexpected RPC packet type - %u, not %u\n",
779 rpccli_pipe_txt(debug_ctx(), cli),
780 prhdr->pkt_type,
781 expected_pkt_type));
782 return NT_STATUS_INVALID_INFO_CLASS;
785 /* Do this just before return - we don't want to modify any rpc header
786 data before now as we may have needed to do cryptographic actions on
787 it before. */
789 if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
790 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
791 "setting fragment first/last ON.\n"));
792 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
795 return NT_STATUS_OK;
798 /****************************************************************************
799 Ensure we eat the just processed pdu from the current_pdu prs_struct.
800 Normally the frag_len and buffer size will match, but on the first trans
801 reply there is a theoretical chance that buffer size > frag_len, so we must
802 deal with that.
803 ****************************************************************************/
805 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
807 uint32 current_pdu_len = prs_data_size(current_pdu);
809 if (current_pdu_len < prhdr->frag_len) {
810 return NT_STATUS_BUFFER_TOO_SMALL;
813 /* Common case. */
814 if (current_pdu_len == (uint32)prhdr->frag_len) {
815 prs_mem_free(current_pdu);
816 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
817 /* Make current_pdu dynamic with no memory. */
818 prs_give_memory(current_pdu, 0, 0, True);
819 return NT_STATUS_OK;
823 * Oh no ! More data in buffer than we processed in current pdu.
824 * Cheat. Move the data down and shrink the buffer.
827 memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
828 current_pdu_len - prhdr->frag_len);
830 /* Remember to set the read offset back to zero. */
831 prs_set_offset(current_pdu, 0);
833 /* Shrink the buffer. */
834 if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
835 return NT_STATUS_BUFFER_TOO_SMALL;
838 return NT_STATUS_OK;
841 /****************************************************************************
842 Send data on an rpc pipe via trans. The prs_struct data must be the last
843 pdu fragment of an NDR data stream.
845 Receive response data from an rpc pipe, which may be large...
847 Read the first fragment: unfortunately have to use SMBtrans for the first
848 bit, then SMBreadX for subsequent bits.
850 If first fragment received also wasn't the last fragment, continue
851 getting fragments until we _do_ receive the last fragment.
853 Request/Response PDU's look like the following...
855 |<------------------PDU len----------------------------------------------->|
856 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
858 +------------+-----------------+-------------+---------------+-------------+
859 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
860 +------------+-----------------+-------------+---------------+-------------+
862 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
863 signing & sealing being negotiated.
865 ****************************************************************************/
867 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
868 prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
869 prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
870 uint8 expected_pkt_type)
872 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
873 char *rparam = NULL;
874 uint32 rparam_len = 0;
875 char *pdata = prs_data_p(data);
876 uint32 data_len = prs_offset(data);
877 char *prdata = NULL;
878 uint32 rdata_len = 0;
879 uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
880 uint32 current_rbuf_offset = 0;
881 prs_struct current_pdu;
883 #ifdef DEVELOPER
884 /* Ensure we're not sending too much. */
885 SMB_ASSERT(data_len <= max_data);
886 #endif
888 /* Set up the current pdu parse struct. */
889 prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
891 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
893 switch (cli->transport_type) {
894 case NCACN_NP: {
895 uint16 setup[2];
896 /* Create setup parameters - must be in native byte order. */
897 setup[0] = TRANSACT_DCERPCCMD;
898 setup[1] = cli->trans.np.fnum; /* Pipe file handle. */
901 * Send the last (or only) fragment of an RPC request. For
902 * small amounts of data (about 1024 bytes or so) the RPC
903 * request and response appears in a SMBtrans request and
904 * response.
907 if (!cli_api_pipe(cli->trans.np.cli, "\\PIPE\\",
908 setup, 2, 0, /* Setup, length, max */
909 NULL, 0, 0, /* Params, length, max */
910 pdata, data_len, max_data, /* data, length,
911 * max */
912 &rparam, &rparam_len, /* return params,
913 * len */
914 &prdata, &rdata_len)) /* return data, len */
916 DEBUG(0, ("rpc_api_pipe: %s returned critical error. "
917 "Error was %s\n",
918 rpccli_pipe_txt(debug_ctx(), cli),
919 cli_errstr(cli->trans.np.cli)));
920 ret = cli_get_nt_error(cli->trans.np.cli);
921 SAFE_FREE(rparam);
922 SAFE_FREE(prdata);
923 goto err;
925 break;
927 case NCACN_IP_TCP:
928 case NCACN_UNIX_STREAM:
930 ssize_t nwritten, nread;
931 nwritten = write_data(cli->trans.sock.fd, pdata, data_len);
932 if (nwritten == -1) {
933 ret = map_nt_error_from_unix(errno);
934 DEBUG(0, ("rpc_api_pipe: write_data returned %s\n",
935 strerror(errno)));
936 goto err;
938 rparam = NULL;
939 prdata = SMB_MALLOC_ARRAY(char, 1);
940 if (prdata == NULL) {
941 return NT_STATUS_NO_MEMORY;
943 nread = sys_read(cli->trans.sock.fd, prdata, 1);
944 if (nread == 0) {
945 SAFE_FREE(prdata);
947 if (nread == -1) {
948 ret = NT_STATUS_END_OF_FILE;
949 goto err;
951 rdata_len = nread;
952 break;
954 default:
955 DEBUG(0, ("unknown transport type %d\n",
956 cli->transport_type));
957 return NT_STATUS_INTERNAL_ERROR;
960 /* Throw away returned params - we know we won't use them. */
962 SAFE_FREE(rparam);
964 if (prdata == NULL) {
965 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
966 rpccli_pipe_txt(debug_ctx(), cli)));
967 /* Yes - some calls can truely return no data... */
968 prs_mem_free(&current_pdu);
969 return NT_STATUS_OK;
973 * Give this memory as dynamic to the current pdu.
976 prs_give_memory(&current_pdu, prdata, rdata_len, True);
978 /* Ensure we can mess with the return prs_struct. */
979 SMB_ASSERT(UNMARSHALLING(rbuf));
980 SMB_ASSERT(prs_data_size(rbuf) == 0);
982 /* Make rbuf dynamic with no memory. */
983 prs_give_memory(rbuf, 0, 0, True);
985 while(1) {
986 RPC_HDR rhdr;
987 char *ret_data;
988 uint32 ret_data_len;
990 /* Ensure we have enough data for a pdu. */
991 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
992 if (!NT_STATUS_IS_OK(ret)) {
993 goto err;
996 /* We pass in rbuf here so if the alloc hint is set correctly
997 we can set the output size and avoid reallocs. */
999 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
1000 &ret_data, &ret_data_len, rbuf);
1002 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
1003 prs_data_size(&current_pdu), current_rbuf_offset ));
1005 if (!NT_STATUS_IS_OK(ret)) {
1006 goto err;
1009 if ((rhdr.flags & RPC_FLG_FIRST)) {
1010 if (rhdr.pack_type[0] == 0) {
1011 /* Set the data type correctly for big-endian data on the first packet. */
1012 DEBUG(10,("rpc_api_pipe: On %s "
1013 "PDU data format is big-endian.\n",
1014 rpccli_pipe_txt(debug_ctx(), cli)));
1016 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
1017 } else {
1018 /* Check endianness on subsequent packets. */
1019 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
1020 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
1021 rbuf->bigendian_data ? "big" : "little",
1022 current_pdu.bigendian_data ? "big" : "little" ));
1023 ret = NT_STATUS_INVALID_PARAMETER;
1024 goto err;
1029 /* Now copy the data portion out of the pdu into rbuf. */
1030 if (!prs_force_grow(rbuf, ret_data_len)) {
1031 ret = NT_STATUS_NO_MEMORY;
1032 goto err;
1034 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
1035 current_rbuf_offset += ret_data_len;
1037 /* See if we've finished with all the data in current_pdu yet ? */
1038 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
1039 if (!NT_STATUS_IS_OK(ret)) {
1040 goto err;
1043 if (rhdr.flags & RPC_FLG_LAST) {
1044 break; /* We're done. */
1048 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1049 rpccli_pipe_txt(debug_ctx(), cli),
1050 (unsigned int)prs_data_size(rbuf) ));
1052 prs_mem_free(&current_pdu);
1053 return NT_STATUS_OK;
1055 err:
1057 prs_mem_free(&current_pdu);
1058 prs_mem_free(rbuf);
1059 return ret;
1062 /*******************************************************************
1063 Creates krb5 auth bind.
1064 ********************************************************************/
1066 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1067 enum pipe_auth_level auth_level,
1068 RPC_HDR_AUTH *pauth_out,
1069 prs_struct *auth_data)
1071 #ifdef HAVE_KRB5
1072 int ret;
1073 struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1074 DATA_BLOB tkt = data_blob_null;
1075 DATA_BLOB tkt_wrapped = data_blob_null;
1077 /* We may change the pad length before marshalling. */
1078 init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
1080 DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1081 a->service_principal ));
1083 /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1085 ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1086 &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
1088 if (ret) {
1089 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1090 "failed with %s\n",
1091 a->service_principal,
1092 error_message(ret) ));
1094 data_blob_free(&tkt);
1095 prs_mem_free(auth_data);
1096 return NT_STATUS_INVALID_PARAMETER;
1099 /* wrap that up in a nice GSS-API wrapping */
1100 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1102 data_blob_free(&tkt);
1104 /* Auth len in the rpc header doesn't include auth_header. */
1105 if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1106 data_blob_free(&tkt_wrapped);
1107 prs_mem_free(auth_data);
1108 return NT_STATUS_NO_MEMORY;
1111 DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1112 dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1114 data_blob_free(&tkt_wrapped);
1115 return NT_STATUS_OK;
1116 #else
1117 return NT_STATUS_INVALID_PARAMETER;
1118 #endif
1121 /*******************************************************************
1122 Creates SPNEGO NTLMSSP auth bind.
1123 ********************************************************************/
1125 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1126 enum pipe_auth_level auth_level,
1127 RPC_HDR_AUTH *pauth_out,
1128 prs_struct *auth_data)
1130 NTSTATUS nt_status;
1131 DATA_BLOB null_blob = data_blob_null;
1132 DATA_BLOB request = data_blob_null;
1133 DATA_BLOB spnego_msg = data_blob_null;
1135 /* We may change the pad length before marshalling. */
1136 init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1138 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1139 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1140 null_blob,
1141 &request);
1143 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1144 data_blob_free(&request);
1145 prs_mem_free(auth_data);
1146 return nt_status;
1149 /* Wrap this in SPNEGO. */
1150 spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1152 data_blob_free(&request);
1154 /* Auth len in the rpc header doesn't include auth_header. */
1155 if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1156 data_blob_free(&spnego_msg);
1157 prs_mem_free(auth_data);
1158 return NT_STATUS_NO_MEMORY;
1161 DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1162 dump_data(5, spnego_msg.data, spnego_msg.length);
1164 data_blob_free(&spnego_msg);
1165 return NT_STATUS_OK;
1168 /*******************************************************************
1169 Creates NTLMSSP auth bind.
1170 ********************************************************************/
1172 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1173 enum pipe_auth_level auth_level,
1174 RPC_HDR_AUTH *pauth_out,
1175 prs_struct *auth_data)
1177 NTSTATUS nt_status;
1178 DATA_BLOB null_blob = data_blob_null;
1179 DATA_BLOB request = data_blob_null;
1181 /* We may change the pad length before marshalling. */
1182 init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1184 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1185 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1186 null_blob,
1187 &request);
1189 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1190 data_blob_free(&request);
1191 prs_mem_free(auth_data);
1192 return nt_status;
1195 /* Auth len in the rpc header doesn't include auth_header. */
1196 if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1197 data_blob_free(&request);
1198 prs_mem_free(auth_data);
1199 return NT_STATUS_NO_MEMORY;
1202 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1203 dump_data(5, request.data, request.length);
1205 data_blob_free(&request);
1206 return NT_STATUS_OK;
1209 /*******************************************************************
1210 Creates schannel auth bind.
1211 ********************************************************************/
1213 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1214 enum pipe_auth_level auth_level,
1215 RPC_HDR_AUTH *pauth_out,
1216 prs_struct *auth_data)
1218 RPC_AUTH_SCHANNEL_NEG schannel_neg;
1220 /* We may change the pad length before marshalling. */
1221 init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1223 /* Use lp_workgroup() if domain not specified */
1225 if (!cli->auth->domain || !cli->auth->domain[0]) {
1226 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1227 if (cli->auth->domain == NULL) {
1228 return NT_STATUS_NO_MEMORY;
1232 init_rpc_auth_schannel_neg(&schannel_neg, cli->auth->domain,
1233 global_myname());
1236 * Now marshall the data into the auth parse_struct.
1239 if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1240 &schannel_neg, auth_data, 0)) {
1241 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1242 prs_mem_free(auth_data);
1243 return NT_STATUS_NO_MEMORY;
1246 return NT_STATUS_OK;
1249 /*******************************************************************
1250 Creates the internals of a DCE/RPC bind request or alter context PDU.
1251 ********************************************************************/
1253 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1254 prs_struct *rpc_out,
1255 uint32 rpc_call_id,
1256 const RPC_IFACE *abstract,
1257 const RPC_IFACE *transfer,
1258 RPC_HDR_AUTH *phdr_auth,
1259 prs_struct *pauth_info)
1261 RPC_HDR hdr;
1262 RPC_HDR_RB hdr_rb;
1263 RPC_CONTEXT rpc_ctx;
1264 uint16 auth_len = prs_offset(pauth_info);
1265 uint8 ss_padding_len = 0;
1266 uint16 frag_len = 0;
1268 /* create the RPC context. */
1269 init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1271 /* create the bind request RPC_HDR_RB */
1272 init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1274 /* Start building the frag length. */
1275 frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1277 /* Do we need to pad ? */
1278 if (auth_len) {
1279 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1280 if (data_len % 8) {
1281 ss_padding_len = 8 - (data_len % 8);
1282 phdr_auth->auth_pad_len = ss_padding_len;
1284 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1287 /* Create the request RPC_HDR */
1288 init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1290 /* Marshall the RPC header */
1291 if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) {
1292 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1293 return NT_STATUS_NO_MEMORY;
1296 /* Marshall the bind request data */
1297 if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1298 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1299 return NT_STATUS_NO_MEMORY;
1303 * Grow the outgoing buffer to store any auth info.
1306 if(auth_len != 0) {
1307 if (ss_padding_len) {
1308 char pad[8];
1309 memset(pad, '\0', 8);
1310 if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1311 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1312 return NT_STATUS_NO_MEMORY;
1316 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1317 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1318 return NT_STATUS_NO_MEMORY;
1322 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1323 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1324 return NT_STATUS_NO_MEMORY;
1328 return NT_STATUS_OK;
1331 /*******************************************************************
1332 Creates a DCE/RPC bind request.
1333 ********************************************************************/
1335 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1336 prs_struct *rpc_out,
1337 uint32 rpc_call_id,
1338 const RPC_IFACE *abstract,
1339 const RPC_IFACE *transfer,
1340 enum pipe_auth_type auth_type,
1341 enum pipe_auth_level auth_level)
1343 RPC_HDR_AUTH hdr_auth;
1344 prs_struct auth_info;
1345 NTSTATUS ret = NT_STATUS_OK;
1347 ZERO_STRUCT(hdr_auth);
1348 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1349 return NT_STATUS_NO_MEMORY;
1351 switch (auth_type) {
1352 case PIPE_AUTH_TYPE_SCHANNEL:
1353 ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1354 if (!NT_STATUS_IS_OK(ret)) {
1355 prs_mem_free(&auth_info);
1356 return ret;
1358 break;
1360 case PIPE_AUTH_TYPE_NTLMSSP:
1361 ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1362 if (!NT_STATUS_IS_OK(ret)) {
1363 prs_mem_free(&auth_info);
1364 return ret;
1366 break;
1368 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1369 ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1370 if (!NT_STATUS_IS_OK(ret)) {
1371 prs_mem_free(&auth_info);
1372 return ret;
1374 break;
1376 case PIPE_AUTH_TYPE_KRB5:
1377 ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1378 if (!NT_STATUS_IS_OK(ret)) {
1379 prs_mem_free(&auth_info);
1380 return ret;
1382 break;
1384 case PIPE_AUTH_TYPE_NONE:
1385 break;
1387 default:
1388 /* "Can't" happen. */
1389 return NT_STATUS_INVALID_INFO_CLASS;
1392 ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1393 rpc_out,
1394 rpc_call_id,
1395 abstract,
1396 transfer,
1397 &hdr_auth,
1398 &auth_info);
1400 prs_mem_free(&auth_info);
1401 return ret;
1404 /*******************************************************************
1405 Create and add the NTLMSSP sign/seal auth header and data.
1406 ********************************************************************/
1408 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1409 RPC_HDR *phdr,
1410 uint32 ss_padding_len,
1411 prs_struct *outgoing_pdu)
1413 RPC_HDR_AUTH auth_info;
1414 NTSTATUS status;
1415 DATA_BLOB auth_blob = data_blob_null;
1416 uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1418 if (!cli->auth->a_u.ntlmssp_state) {
1419 return NT_STATUS_INVALID_PARAMETER;
1422 /* Init and marshall the auth header. */
1423 init_rpc_hdr_auth(&auth_info,
1424 map_pipe_auth_type_to_rpc_auth_type(
1425 cli->auth->auth_type),
1426 cli->auth->auth_level,
1427 ss_padding_len,
1428 1 /* context id. */);
1430 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1431 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1432 data_blob_free(&auth_blob);
1433 return NT_STATUS_NO_MEMORY;
1436 switch (cli->auth->auth_level) {
1437 case PIPE_AUTH_LEVEL_PRIVACY:
1438 /* Data portion is encrypted. */
1439 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1440 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1441 data_and_pad_len,
1442 (unsigned char *)prs_data_p(outgoing_pdu),
1443 (size_t)prs_offset(outgoing_pdu),
1444 &auth_blob);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 data_blob_free(&auth_blob);
1447 return status;
1449 break;
1451 case PIPE_AUTH_LEVEL_INTEGRITY:
1452 /* Data is signed. */
1453 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1454 (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1455 data_and_pad_len,
1456 (unsigned char *)prs_data_p(outgoing_pdu),
1457 (size_t)prs_offset(outgoing_pdu),
1458 &auth_blob);
1459 if (!NT_STATUS_IS_OK(status)) {
1460 data_blob_free(&auth_blob);
1461 return status;
1463 break;
1465 default:
1466 /* Can't happen. */
1467 smb_panic("bad auth level");
1468 /* Notreached. */
1469 return NT_STATUS_INVALID_PARAMETER;
1472 /* Finally marshall the blob. */
1474 if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1475 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1476 (unsigned int)NTLMSSP_SIG_SIZE));
1477 data_blob_free(&auth_blob);
1478 return NT_STATUS_NO_MEMORY;
1481 data_blob_free(&auth_blob);
1482 return NT_STATUS_OK;
1485 /*******************************************************************
1486 Create and add the schannel sign/seal auth header and data.
1487 ********************************************************************/
1489 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1490 RPC_HDR *phdr,
1491 uint32 ss_padding_len,
1492 prs_struct *outgoing_pdu)
1494 RPC_HDR_AUTH auth_info;
1495 RPC_AUTH_SCHANNEL_CHK verf;
1496 struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
1497 char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1498 size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1500 if (!sas) {
1501 return NT_STATUS_INVALID_PARAMETER;
1504 /* Init and marshall the auth header. */
1505 init_rpc_hdr_auth(&auth_info,
1506 map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1507 cli->auth->auth_level,
1508 ss_padding_len,
1509 1 /* context id. */);
1511 if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1512 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1513 return NT_STATUS_NO_MEMORY;
1516 switch (cli->auth->auth_level) {
1517 case PIPE_AUTH_LEVEL_PRIVACY:
1518 case PIPE_AUTH_LEVEL_INTEGRITY:
1519 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1520 sas->seq_num));
1522 schannel_encode(sas,
1523 cli->auth->auth_level,
1524 SENDER_IS_INITIATOR,
1525 &verf,
1526 data_p,
1527 data_and_pad_len);
1529 sas->seq_num++;
1530 break;
1532 default:
1533 /* Can't happen. */
1534 smb_panic("bad auth level");
1535 /* Notreached. */
1536 return NT_STATUS_INVALID_PARAMETER;
1539 /* Finally marshall the blob. */
1540 smb_io_rpc_auth_schannel_chk("",
1541 RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1542 &verf,
1543 outgoing_pdu,
1546 return NT_STATUS_OK;
1549 /*******************************************************************
1550 Calculate how much data we're going to send in this packet, also
1551 work out any sign/seal padding length.
1552 ********************************************************************/
1554 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1555 uint32 data_left,
1556 uint16 *p_frag_len,
1557 uint16 *p_auth_len,
1558 uint32 *p_ss_padding)
1560 uint32 data_space, data_len;
1562 switch (cli->auth->auth_level) {
1563 case PIPE_AUTH_LEVEL_NONE:
1564 case PIPE_AUTH_LEVEL_CONNECT:
1565 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1566 data_len = MIN(data_space, data_left);
1567 *p_ss_padding = 0;
1568 *p_auth_len = 0;
1569 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1570 return data_len;
1572 case PIPE_AUTH_LEVEL_INTEGRITY:
1573 case PIPE_AUTH_LEVEL_PRIVACY:
1574 /* Treat the same for all authenticated rpc requests. */
1575 switch(cli->auth->auth_type) {
1576 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1577 case PIPE_AUTH_TYPE_NTLMSSP:
1578 *p_auth_len = NTLMSSP_SIG_SIZE;
1579 break;
1580 case PIPE_AUTH_TYPE_SCHANNEL:
1581 *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1582 break;
1583 default:
1584 smb_panic("bad auth type");
1585 break;
1588 data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1589 RPC_HDR_AUTH_LEN - *p_auth_len;
1591 data_len = MIN(data_space, data_left);
1592 if (data_len % 8) {
1593 *p_ss_padding = 8 - (data_len % 8);
1595 *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */
1596 data_len + *p_ss_padding + /* data plus padding. */
1597 RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */
1598 return data_len;
1600 default:
1601 smb_panic("bad auth level");
1602 /* Notreached. */
1603 return 0;
1607 /*******************************************************************
1608 External interface.
1609 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1610 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1611 and deals with signing/sealing details.
1612 ********************************************************************/
1614 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1615 uint8 op_num,
1616 prs_struct *in_data,
1617 prs_struct *out_data)
1619 NTSTATUS ret;
1620 uint32 data_left = prs_offset(in_data);
1621 uint32 alloc_hint = prs_offset(in_data);
1622 uint32 data_sent_thistime = 0;
1623 uint32 current_data_offset = 0;
1624 uint32 call_id = get_rpc_call_id();
1625 char pad[8];
1626 prs_struct outgoing_pdu;
1628 memset(pad, '\0', 8);
1630 if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1631 /* Server is screwed up ! */
1632 return NT_STATUS_INVALID_PARAMETER;
1635 if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1636 return NT_STATUS_NO_MEMORY;
1638 while (1) {
1639 RPC_HDR hdr;
1640 RPC_HDR_REQ hdr_req;
1641 uint16 auth_len = 0;
1642 uint16 frag_len = 0;
1643 uint8 flags = 0;
1644 uint32 ss_padding = 0;
1646 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1647 &frag_len, &auth_len, &ss_padding);
1649 if (current_data_offset == 0) {
1650 flags = RPC_FLG_FIRST;
1653 if (data_sent_thistime == data_left) {
1654 flags |= RPC_FLG_LAST;
1657 /* Create and marshall the header and request header. */
1658 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1660 if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) {
1661 prs_mem_free(&outgoing_pdu);
1662 return NT_STATUS_NO_MEMORY;
1665 /* Create the rpc request RPC_HDR_REQ */
1666 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1668 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1669 prs_mem_free(&outgoing_pdu);
1670 return NT_STATUS_NO_MEMORY;
1673 /* Copy in the data, plus any ss padding. */
1674 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1675 prs_mem_free(&outgoing_pdu);
1676 return NT_STATUS_NO_MEMORY;
1679 /* Copy the sign/seal padding data. */
1680 if (ss_padding) {
1681 if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1682 prs_mem_free(&outgoing_pdu);
1683 return NT_STATUS_NO_MEMORY;
1687 /* Generate any auth sign/seal and add the auth footer. */
1688 if (auth_len) {
1689 switch (cli->auth->auth_type) {
1690 case PIPE_AUTH_TYPE_NONE:
1691 break;
1692 case PIPE_AUTH_TYPE_NTLMSSP:
1693 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1694 ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1695 if (!NT_STATUS_IS_OK(ret)) {
1696 prs_mem_free(&outgoing_pdu);
1697 return ret;
1699 break;
1700 case PIPE_AUTH_TYPE_SCHANNEL:
1701 ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1702 if (!NT_STATUS_IS_OK(ret)) {
1703 prs_mem_free(&outgoing_pdu);
1704 return ret;
1706 break;
1707 default:
1708 smb_panic("bad auth type");
1709 break; /* notreached */
1713 /* Actually send the packet. */
1714 if (flags & RPC_FLG_LAST) {
1715 /* Last packet - send the data, get the reply and return. */
1716 ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1717 prs_mem_free(&outgoing_pdu);
1719 if ((DEBUGLEVEL >= 50)
1720 && (cli->transport_type == NCACN_NP)) {
1721 char *dump_name = NULL;
1722 /* Also capture received data */
1723 if (asprintf(&dump_name, "%s/reply_%s_%d",
1724 get_dyn_LOGFILEBASE(),
1725 cli->trans.np.pipe_name, op_num) > 0) {
1726 prs_dump(dump_name, op_num, out_data);
1727 SAFE_FREE(dump_name);
1731 return ret;
1732 } else {
1733 /* More packets to come - write and continue. */
1734 ssize_t num_written;
1736 switch (cli->transport_type) {
1737 case NCACN_NP:
1738 num_written = cli_write(cli->trans.np.cli,
1739 cli->trans.np.fnum,
1740 8, /* 8 means message mode. */
1741 prs_data_p(&outgoing_pdu),
1742 (off_t)0,
1743 (size_t)hdr.frag_len);
1745 if (num_written != hdr.frag_len) {
1746 prs_mem_free(&outgoing_pdu);
1747 return cli_get_nt_error(
1748 cli->trans.np.cli);
1750 break;
1751 case NCACN_IP_TCP:
1752 case NCACN_UNIX_STREAM:
1753 num_written = write_data(
1754 cli->trans.sock.fd,
1755 prs_data_p(&outgoing_pdu),
1756 (size_t)hdr.frag_len);
1757 if (num_written != hdr.frag_len) {
1758 NTSTATUS status;
1759 status = map_nt_error_from_unix(errno);
1760 prs_mem_free(&outgoing_pdu);
1761 return status;
1763 break;
1764 default:
1765 DEBUG(0, ("unknown transport type %d\n",
1766 cli->transport_type));
1767 return NT_STATUS_INTERNAL_ERROR;
1771 current_data_offset += data_sent_thistime;
1772 data_left -= data_sent_thistime;
1774 /* Reset the marshalling position back to zero. */
1775 if (!prs_set_offset(&outgoing_pdu, 0)) {
1776 prs_mem_free(&outgoing_pdu);
1777 return NT_STATUS_NO_MEMORY;
1781 #if 0
1782 /****************************************************************************
1783 Set the handle state.
1784 ****************************************************************************/
1786 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1787 const char *pipe_name, uint16 device_state)
1789 bool state_set = False;
1790 char param[2];
1791 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1792 char *rparam = NULL;
1793 char *rdata = NULL;
1794 uint32 rparam_len, rdata_len;
1796 if (pipe_name == NULL)
1797 return False;
1799 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1800 cli->fnum, pipe_name, device_state));
1802 /* create parameters: device state */
1803 SSVAL(param, 0, device_state);
1805 /* create setup parameters. */
1806 setup[0] = 0x0001;
1807 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1809 /* send the data on \PIPE\ */
1810 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1811 setup, 2, 0, /* setup, length, max */
1812 param, 2, 0, /* param, length, max */
1813 NULL, 0, 1024, /* data, length, max */
1814 &rparam, &rparam_len, /* return param, length */
1815 &rdata, &rdata_len)) /* return data, length */
1817 DEBUG(5, ("Set Handle state: return OK\n"));
1818 state_set = True;
1821 SAFE_FREE(rparam);
1822 SAFE_FREE(rdata);
1824 return state_set;
1826 #endif
1828 /****************************************************************************
1829 Check the rpc bind acknowledge response.
1830 ****************************************************************************/
1832 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1834 if ( hdr_ba->addr.len == 0) {
1835 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1838 /* check the transfer syntax */
1839 if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1840 (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1841 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1842 return False;
1845 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1846 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1847 hdr_ba->res.num_results, hdr_ba->res.reason));
1850 DEBUG(5,("check_bind_response: accepted!\n"));
1851 return True;
1854 /*******************************************************************
1855 Creates a DCE/RPC bind authentication response.
1856 This is the packet that is sent back to the server once we
1857 have received a BIND-ACK, to finish the third leg of
1858 the authentication handshake.
1859 ********************************************************************/
1861 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1862 uint32 rpc_call_id,
1863 enum pipe_auth_type auth_type,
1864 enum pipe_auth_level auth_level,
1865 DATA_BLOB *pauth_blob,
1866 prs_struct *rpc_out)
1868 RPC_HDR hdr;
1869 RPC_HDR_AUTH hdr_auth;
1870 uint32 pad = 0;
1872 /* Create the request RPC_HDR */
1873 init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1874 RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1875 pauth_blob->length );
1877 /* Marshall it. */
1878 if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1879 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1880 return NT_STATUS_NO_MEMORY;
1884 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1885 about padding - shouldn't this pad to length 8 ? JRA.
1888 /* 4 bytes padding. */
1889 if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1890 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1891 return NT_STATUS_NO_MEMORY;
1894 /* Create the request RPC_HDR_AUTHA */
1895 init_rpc_hdr_auth(&hdr_auth,
1896 map_pipe_auth_type_to_rpc_auth_type(auth_type),
1897 auth_level, 0, 1);
1899 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1900 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1901 return NT_STATUS_NO_MEMORY;
1905 * Append the auth data to the outgoing buffer.
1908 if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1909 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1910 return NT_STATUS_NO_MEMORY;
1913 return NT_STATUS_OK;
1916 /****************************************************************************
1917 Create and send the third packet in an RPC auth.
1918 ****************************************************************************/
1920 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1921 RPC_HDR *phdr,
1922 prs_struct *rbuf,
1923 uint32 rpc_call_id,
1924 enum pipe_auth_type auth_type,
1925 enum pipe_auth_level auth_level)
1927 DATA_BLOB server_response = data_blob_null;
1928 DATA_BLOB client_reply = data_blob_null;
1929 RPC_HDR_AUTH hdr_auth;
1930 NTSTATUS nt_status;
1931 prs_struct rpc_out;
1932 ssize_t ret;
1934 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1935 return NT_STATUS_INVALID_PARAMETER;
1938 /* Process the returned NTLMSSP blob first. */
1939 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1940 return NT_STATUS_INVALID_PARAMETER;
1943 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1944 return NT_STATUS_INVALID_PARAMETER;
1947 /* TODO - check auth_type/auth_level match. */
1949 server_response = data_blob(NULL, phdr->auth_len);
1950 prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1952 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1953 server_response,
1954 &client_reply);
1956 if (!NT_STATUS_IS_OK(nt_status)) {
1957 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1958 data_blob_free(&server_response);
1959 return nt_status;
1962 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1964 nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1965 auth_type, auth_level,
1966 &client_reply, &rpc_out);
1968 if (!NT_STATUS_IS_OK(nt_status)) {
1969 prs_mem_free(&rpc_out);
1970 data_blob_free(&client_reply);
1971 data_blob_free(&server_response);
1972 return nt_status;
1975 switch (cli->transport_type) {
1976 case NCACN_NP:
1977 /* 8 here is named pipe message mode. */
1978 ret = cli_write(cli->trans.np.cli, cli->trans.np.fnum,
1979 0x8, prs_data_p(&rpc_out), 0,
1980 (size_t)prs_offset(&rpc_out));
1981 break;
1983 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1984 nt_status = cli_get_nt_error(cli->trans.np.cli);
1986 case NCACN_IP_TCP:
1987 case NCACN_UNIX_STREAM:
1988 ret = write_data(cli->trans.sock.fd, prs_data_p(&rpc_out),
1989 (size_t)prs_offset(&rpc_out));
1990 if (ret != (ssize_t)prs_offset(&rpc_out)) {
1991 nt_status = map_nt_error_from_unix(errno);
1993 break;
1994 default:
1995 DEBUG(0, ("unknown transport type %d\n", cli->transport_type));
1996 return NT_STATUS_INTERNAL_ERROR;
1999 if (ret != (ssize_t)prs_offset(&rpc_out)) {
2000 DEBUG(0,("rpc_send_auth_auth3: write failed. Return was %s\n",
2001 nt_errstr(nt_status)));
2002 prs_mem_free(&rpc_out);
2003 data_blob_free(&client_reply);
2004 data_blob_free(&server_response);
2005 return nt_status;
2008 DEBUG(5,("rpc_send_auth_auth3: %s sent auth3 response ok.\n",
2009 rpccli_pipe_txt(debug_ctx(), cli)));
2011 prs_mem_free(&rpc_out);
2012 data_blob_free(&client_reply);
2013 data_blob_free(&server_response);
2014 return NT_STATUS_OK;
2017 /*******************************************************************
2018 Creates a DCE/RPC bind alter context authentication request which
2019 may contain a spnego auth blobl
2020 ********************************************************************/
2022 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2023 const RPC_IFACE *abstract,
2024 const RPC_IFACE *transfer,
2025 enum pipe_auth_level auth_level,
2026 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2027 prs_struct *rpc_out)
2029 RPC_HDR_AUTH hdr_auth;
2030 prs_struct auth_info;
2031 NTSTATUS ret = NT_STATUS_OK;
2033 ZERO_STRUCT(hdr_auth);
2034 if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2035 return NT_STATUS_NO_MEMORY;
2037 /* We may change the pad length before marshalling. */
2038 init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
2040 if (pauth_blob->length) {
2041 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2042 prs_mem_free(&auth_info);
2043 return NT_STATUS_NO_MEMORY;
2047 ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
2048 rpc_out,
2049 rpc_call_id,
2050 abstract,
2051 transfer,
2052 &hdr_auth,
2053 &auth_info);
2054 prs_mem_free(&auth_info);
2055 return ret;
2058 /*******************************************************************
2059 Third leg of the SPNEGO bind mechanism - sends alter context PDU
2060 and gets a response.
2061 ********************************************************************/
2063 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
2064 RPC_HDR *phdr,
2065 prs_struct *rbuf,
2066 uint32 rpc_call_id,
2067 const RPC_IFACE *abstract,
2068 const RPC_IFACE *transfer,
2069 enum pipe_auth_type auth_type,
2070 enum pipe_auth_level auth_level)
2072 DATA_BLOB server_spnego_response = data_blob_null;
2073 DATA_BLOB server_ntlm_response = data_blob_null;
2074 DATA_BLOB client_reply = data_blob_null;
2075 DATA_BLOB tmp_blob = data_blob_null;
2076 RPC_HDR_AUTH hdr_auth;
2077 NTSTATUS nt_status;
2078 prs_struct rpc_out;
2080 if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2081 return NT_STATUS_INVALID_PARAMETER;
2084 /* Process the returned NTLMSSP blob first. */
2085 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2086 return NT_STATUS_INVALID_PARAMETER;
2089 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2090 return NT_STATUS_INVALID_PARAMETER;
2093 server_spnego_response = data_blob(NULL, phdr->auth_len);
2094 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2096 /* The server might give us back two challenges - tmp_blob is for the second. */
2097 if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
2098 data_blob_free(&server_spnego_response);
2099 data_blob_free(&server_ntlm_response);
2100 data_blob_free(&tmp_blob);
2101 return NT_STATUS_INVALID_PARAMETER;
2104 /* We're finished with the server spnego response and the tmp_blob. */
2105 data_blob_free(&server_spnego_response);
2106 data_blob_free(&tmp_blob);
2108 nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
2109 server_ntlm_response,
2110 &client_reply);
2112 /* Finished with the server_ntlm response */
2113 data_blob_free(&server_ntlm_response);
2115 if (!NT_STATUS_IS_OK(nt_status)) {
2116 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
2117 data_blob_free(&client_reply);
2118 return nt_status;
2121 /* SPNEGO wrap the client reply. */
2122 tmp_blob = spnego_gen_auth(client_reply);
2123 data_blob_free(&client_reply);
2124 client_reply = tmp_blob;
2125 tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
2127 /* Now prepare the alter context pdu. */
2128 prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
2130 nt_status = create_rpc_alter_context(rpc_call_id,
2131 abstract,
2132 transfer,
2133 auth_level,
2134 &client_reply,
2135 &rpc_out);
2137 data_blob_free(&client_reply);
2139 if (!NT_STATUS_IS_OK(nt_status)) {
2140 prs_mem_free(&rpc_out);
2141 return nt_status;
2144 /* Initialize the returning data struct. */
2145 prs_mem_free(rbuf);
2146 prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
2148 nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
2149 if (!NT_STATUS_IS_OK(nt_status)) {
2150 prs_mem_free(&rpc_out);
2151 return nt_status;
2154 prs_mem_free(&rpc_out);
2156 /* Get the auth blob from the reply. */
2157 if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) {
2158 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
2159 return NT_STATUS_BUFFER_TOO_SMALL;
2162 if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2163 return NT_STATUS_INVALID_PARAMETER;
2166 if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
2167 return NT_STATUS_INVALID_PARAMETER;
2170 server_spnego_response = data_blob(NULL, phdr->auth_len);
2171 prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
2173 /* Check we got a valid auth response. */
2174 if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
2175 data_blob_free(&server_spnego_response);
2176 data_blob_free(&tmp_blob);
2177 return NT_STATUS_INVALID_PARAMETER;
2180 data_blob_free(&server_spnego_response);
2181 data_blob_free(&tmp_blob);
2183 DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2184 "%s.\n", rpccli_pipe_txt(debug_ctx(), cli)));
2186 return NT_STATUS_OK;
2189 /****************************************************************************
2190 Do an rpc bind.
2191 ****************************************************************************/
2193 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2194 struct cli_pipe_auth_data *auth)
2196 RPC_HDR hdr;
2197 RPC_HDR_BA hdr_ba;
2198 prs_struct rpc_out;
2199 prs_struct rbuf;
2200 uint32 rpc_call_id;
2201 NTSTATUS status;
2203 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2204 rpccli_pipe_txt(debug_ctx(), cli),
2205 (unsigned int)auth->auth_type,
2206 (unsigned int)auth->auth_level ));
2208 cli->auth = talloc_move(cli, &auth);
2210 prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2212 rpc_call_id = get_rpc_call_id();
2214 /* Marshall the outgoing data. */
2215 status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2216 &cli->abstract_syntax,
2217 &cli->transfer_syntax,
2218 cli->auth->auth_type,
2219 cli->auth->auth_level);
2221 if (!NT_STATUS_IS_OK(status)) {
2222 prs_mem_free(&rpc_out);
2223 return status;
2226 /* Initialize the incoming data struct. */
2227 prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2229 /* send data on \PIPE\. receive a response */
2230 status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 prs_mem_free(&rpc_out);
2233 return status;
2236 prs_mem_free(&rpc_out);
2238 DEBUG(3,("rpc_pipe_bind: %s bind request returned ok.\n",
2239 rpccli_pipe_txt(debug_ctx(), cli)));
2241 /* Unmarshall the RPC header */
2242 if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) {
2243 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2244 prs_mem_free(&rbuf);
2245 return NT_STATUS_BUFFER_TOO_SMALL;
2248 if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2249 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2250 prs_mem_free(&rbuf);
2251 return NT_STATUS_BUFFER_TOO_SMALL;
2254 if(!check_bind_response(&hdr_ba, &cli->transfer_syntax)) {
2255 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2256 prs_mem_free(&rbuf);
2257 return NT_STATUS_BUFFER_TOO_SMALL;
2260 cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2261 cli->max_recv_frag = hdr_ba.bba.max_rsize;
2263 /* For authenticated binds we may need to do 3 or 4 leg binds. */
2264 switch(cli->auth->auth_type) {
2266 case PIPE_AUTH_TYPE_NONE:
2267 case PIPE_AUTH_TYPE_SCHANNEL:
2268 /* Bind complete. */
2269 break;
2271 case PIPE_AUTH_TYPE_NTLMSSP:
2272 /* Need to send AUTH3 packet - no reply. */
2273 status = rpc_finish_auth3_bind(
2274 cli, &hdr, &rbuf, rpc_call_id,
2275 cli->auth->auth_type,
2276 cli->auth->auth_level);
2277 if (!NT_STATUS_IS_OK(status)) {
2278 prs_mem_free(&rbuf);
2279 return status;
2281 break;
2283 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2284 /* Need to send alter context request and reply. */
2285 status = rpc_finish_spnego_ntlmssp_bind(
2286 cli, &hdr, &rbuf, rpc_call_id,
2287 &cli->abstract_syntax, &cli->transfer_syntax,
2288 cli->auth->auth_type, cli->auth->auth_level);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 prs_mem_free(&rbuf);
2291 return status;
2293 break;
2295 case PIPE_AUTH_TYPE_KRB5:
2296 /* */
2298 default:
2299 DEBUG(0,("cli_finish_bind_auth: unknown auth type "
2300 "%u\n", (unsigned int)cli->auth->auth_type));
2301 prs_mem_free(&rbuf);
2302 return NT_STATUS_INVALID_INFO_CLASS;
2305 /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2306 if (cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP
2307 || cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2308 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2309 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2310 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2311 prs_mem_free(&rbuf);
2312 return NT_STATUS_INVALID_PARAMETER;
2315 if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2316 if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2317 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2318 prs_mem_free(&rbuf);
2319 return NT_STATUS_INVALID_PARAMETER;
2324 prs_mem_free(&rbuf);
2325 return NT_STATUS_OK;
2328 unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
2329 unsigned int timeout)
2331 return cli_set_timeout(cli->trans.np.cli, timeout);
2334 bool rpccli_is_pipe_idx(struct rpc_pipe_client *cli, int pipe_idx)
2336 return ndr_syntax_id_equal(&cli->abstract_syntax,
2337 pipe_names[pipe_idx].abstr_syntax);
2340 bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16])
2342 if ((cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2343 || (cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2344 memcpy(nt_hash, cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2345 return true;
2348 if (cli->transport_type == NCACN_NP) {
2349 E_md4hash(cli->trans.np.cli->pwd.password, nt_hash);
2350 return true;
2353 return false;
2356 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
2358 if (p->transport_type == NCACN_NP) {
2359 return p->trans.np.cli;
2361 return NULL;
2364 static int rpc_pipe_destructor(struct rpc_pipe_client *p)
2366 if (p->transport_type == NCACN_NP) {
2367 bool ret;
2368 ret = cli_close(p->trans.np.cli, p->trans.np.fnum);
2369 if (!ret) {
2370 DEBUG(1, ("rpc_pipe_destructor: cli_close failed on "
2371 "pipe %s. Error was %s\n",
2372 rpccli_pipe_txt(debug_ctx(), p),
2373 cli_errstr(p->trans.np.cli)));
2376 DEBUG(10, ("rpc_pipe_destructor: closed %s\n",
2377 rpccli_pipe_txt(debug_ctx(), p)));
2379 DLIST_REMOVE(p->trans.np.cli->pipe_list, p);
2380 return ret ? -1 : 0;
2383 return -1;
2386 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2387 struct cli_pipe_auth_data **presult)
2389 struct cli_pipe_auth_data *result;
2391 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2392 if (result == NULL) {
2393 return NT_STATUS_NO_MEMORY;
2396 result->auth_type = PIPE_AUTH_TYPE_NONE;
2397 result->auth_level = PIPE_AUTH_LEVEL_NONE;
2399 result->user_name = talloc_strdup(result, "");
2400 result->domain = talloc_strdup(result, "");
2401 if ((result->user_name == NULL) || (result->domain == NULL)) {
2402 TALLOC_FREE(result);
2403 return NT_STATUS_NO_MEMORY;
2406 *presult = result;
2407 return NT_STATUS_OK;
2410 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2412 ntlmssp_end(&auth->a_u.ntlmssp_state);
2413 return 0;
2416 NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2417 enum pipe_auth_type auth_type,
2418 enum pipe_auth_level auth_level,
2419 const char *domain,
2420 const char *username,
2421 const char *password,
2422 struct cli_pipe_auth_data **presult)
2424 struct cli_pipe_auth_data *result;
2425 NTSTATUS status;
2427 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2428 if (result == NULL) {
2429 return NT_STATUS_NO_MEMORY;
2432 result->auth_type = auth_type;
2433 result->auth_level = auth_level;
2435 result->user_name = talloc_strdup(result, username);
2436 result->domain = talloc_strdup(result, domain);
2437 if ((result->user_name == NULL) || (result->domain == NULL)) {
2438 status = NT_STATUS_NO_MEMORY;
2439 goto fail;
2442 status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 goto fail;
2447 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2449 status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2450 if (!NT_STATUS_IS_OK(status)) {
2451 goto fail;
2454 status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2455 if (!NT_STATUS_IS_OK(status)) {
2456 goto fail;
2459 status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2460 if (!NT_STATUS_IS_OK(status)) {
2461 goto fail;
2465 * Turn off sign+seal to allow selected auth level to turn it back on.
2467 result->a_u.ntlmssp_state->neg_flags &=
2468 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2470 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2471 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2472 } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2473 result->a_u.ntlmssp_state->neg_flags
2474 |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2477 *presult = result;
2478 return NT_STATUS_OK;
2480 fail:
2481 TALLOC_FREE(result);
2482 return status;
2485 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2486 enum pipe_auth_level auth_level,
2487 const uint8_t sess_key[16],
2488 struct cli_pipe_auth_data **presult)
2490 struct cli_pipe_auth_data *result;
2492 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2493 if (result == NULL) {
2494 return NT_STATUS_NO_MEMORY;
2497 result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2498 result->auth_level = auth_level;
2500 result->user_name = talloc_strdup(result, "");
2501 result->domain = talloc_strdup(result, domain);
2502 if ((result->user_name == NULL) || (result->domain == NULL)) {
2503 goto fail;
2506 result->a_u.schannel_auth = talloc(result,
2507 struct schannel_auth_struct);
2508 if (result->a_u.schannel_auth == NULL) {
2509 goto fail;
2512 memcpy(result->a_u.schannel_auth->sess_key, sess_key,
2513 sizeof(result->a_u.schannel_auth->sess_key));
2514 result->a_u.schannel_auth->seq_num = 0;
2516 *presult = result;
2517 return NT_STATUS_OK;
2519 fail:
2520 TALLOC_FREE(result);
2521 return NT_STATUS_NO_MEMORY;
2524 #ifdef HAVE_KRB5
2525 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2527 data_blob_free(&auth->session_key);
2528 return 0;
2530 #endif
2532 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2533 enum pipe_auth_level auth_level,
2534 const char *service_princ,
2535 const char *username,
2536 const char *password,
2537 struct cli_pipe_auth_data **presult)
2539 #ifdef HAVE_KRB5
2540 struct cli_pipe_auth_data *result;
2542 if ((username != NULL) && (password != NULL)) {
2543 int ret = kerberos_kinit_password(username, password, 0, NULL);
2544 if (ret != 0) {
2545 return NT_STATUS_ACCESS_DENIED;
2549 result = talloc(mem_ctx, struct cli_pipe_auth_data);
2550 if (result == NULL) {
2551 return NT_STATUS_NO_MEMORY;
2554 result->auth_type = PIPE_AUTH_TYPE_KRB5;
2555 result->auth_level = auth_level;
2558 * Username / domain need fixing!
2560 result->user_name = talloc_strdup(result, "");
2561 result->domain = talloc_strdup(result, "");
2562 if ((result->user_name == NULL) || (result->domain == NULL)) {
2563 goto fail;
2566 result->a_u.kerberos_auth = TALLOC_ZERO_P(
2567 result, struct kerberos_auth_struct);
2568 if (result->a_u.kerberos_auth == NULL) {
2569 goto fail;
2571 talloc_set_destructor(result->a_u.kerberos_auth,
2572 cli_auth_kerberos_data_destructor);
2574 result->a_u.kerberos_auth->service_principal = talloc_strdup(
2575 result, service_princ);
2576 if (result->a_u.kerberos_auth->service_principal == NULL) {
2577 goto fail;
2580 *presult = result;
2581 return NT_STATUS_OK;
2583 fail:
2584 TALLOC_FREE(result);
2585 return NT_STATUS_NO_MEMORY;
2586 #else
2587 return NT_STATUS_NOT_SUPPORTED;
2588 #endif
2591 static int rpc_pipe_sock_destructor(struct rpc_pipe_client *p)
2593 close(p->trans.sock.fd);
2594 return 0;
2598 * Create an rpc pipe client struct, connecting to a tcp port.
2600 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2601 uint16_t port,
2602 const struct ndr_syntax_id *abstract_syntax,
2603 struct rpc_pipe_client **presult)
2605 struct rpc_pipe_client *result;
2606 struct sockaddr_storage addr;
2607 NTSTATUS status;
2609 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2610 if (result == NULL) {
2611 return NT_STATUS_NO_MEMORY;
2614 result->transport_type = NCACN_IP_TCP;
2616 result->abstract_syntax = *abstract_syntax;
2617 result->transfer_syntax = ndr_transfer_syntax;
2619 result->desthost = talloc_strdup(result, host);
2620 result->srv_name_slash = talloc_asprintf_strupper_m(
2621 result, "\\\\%s", result->desthost);
2622 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2623 status = NT_STATUS_NO_MEMORY;
2624 goto fail;
2627 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2628 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2630 if (!resolve_name(host, &addr, 0)) {
2631 status = NT_STATUS_NOT_FOUND;
2632 goto fail;
2635 result->trans.sock.fd = open_socket_out(SOCK_STREAM, &addr, port, 60);
2636 if (result->trans.sock.fd == -1) {
2637 status = map_nt_error_from_unix(errno);
2638 goto fail;
2641 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2643 *presult = result;
2644 return NT_STATUS_OK;
2646 fail:
2647 TALLOC_FREE(result);
2648 return status;
2652 * Determine the tcp port on which a dcerpc interface is listening
2653 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2654 * target host.
2656 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2657 const struct ndr_syntax_id *abstract_syntax,
2658 uint16_t *pport)
2660 NTSTATUS status;
2661 struct rpc_pipe_client *epm_pipe = NULL;
2662 struct cli_pipe_auth_data *auth = NULL;
2663 struct dcerpc_binding *map_binding = NULL;
2664 struct dcerpc_binding *res_binding = NULL;
2665 struct epm_twr_t *map_tower = NULL;
2666 struct epm_twr_t *res_towers = NULL;
2667 struct policy_handle *entry_handle = NULL;
2668 uint32_t num_towers = 0;
2669 uint32_t max_towers = 1;
2670 struct epm_twr_p_t towers;
2671 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2673 if (pport == NULL) {
2674 status = NT_STATUS_INVALID_PARAMETER;
2675 goto done;
2678 /* open the connection to the endpoint mapper */
2679 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2680 &ndr_table_epmapper.syntax_id,
2681 &epm_pipe);
2683 if (!NT_STATUS_IS_OK(status)) {
2684 goto done;
2687 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2688 if (!NT_STATUS_IS_OK(status)) {
2689 goto done;
2692 status = rpc_pipe_bind(epm_pipe, auth);
2693 if (!NT_STATUS_IS_OK(status)) {
2694 goto done;
2697 /* create tower for asking the epmapper */
2699 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2700 if (map_binding == NULL) {
2701 status = NT_STATUS_NO_MEMORY;
2702 goto done;
2705 map_binding->transport = NCACN_IP_TCP;
2706 map_binding->object = *abstract_syntax;
2707 map_binding->host = host; /* needed? */
2708 map_binding->endpoint = "0"; /* correct? needed? */
2710 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2711 if (map_tower == NULL) {
2712 status = NT_STATUS_NO_MEMORY;
2713 goto done;
2716 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2717 &(map_tower->tower));
2718 if (!NT_STATUS_IS_OK(status)) {
2719 goto done;
2722 /* allocate further parameters for the epm_Map call */
2724 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2725 if (res_towers == NULL) {
2726 status = NT_STATUS_NO_MEMORY;
2727 goto done;
2729 towers.twr = res_towers;
2731 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2732 if (entry_handle == NULL) {
2733 status = NT_STATUS_NO_MEMORY;
2734 goto done;
2737 /* ask the endpoint mapper for the port */
2739 status = rpccli_epm_Map(epm_pipe,
2740 tmp_ctx,
2741 CONST_DISCARD(struct GUID *,
2742 &(abstract_syntax->uuid)),
2743 map_tower,
2744 entry_handle,
2745 max_towers,
2746 &num_towers,
2747 &towers);
2749 if (!NT_STATUS_IS_OK(status)) {
2750 goto done;
2753 if (num_towers != 1) {
2754 status = NT_STATUS_UNSUCCESSFUL;
2755 goto done;
2758 /* extract the port from the answer */
2760 status = dcerpc_binding_from_tower(tmp_ctx,
2761 &(towers.twr->tower),
2762 &res_binding);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 goto done;
2767 /* are further checks here necessary? */
2768 if (res_binding->transport != NCACN_IP_TCP) {
2769 status = NT_STATUS_UNSUCCESSFUL;
2770 goto done;
2773 *pport = (uint16_t)atoi(res_binding->endpoint);
2775 done:
2776 TALLOC_FREE(tmp_ctx);
2777 return status;
2781 * Create a rpc pipe client struct, connecting to a host via tcp.
2782 * The port is determined by asking the endpoint mapper on the given
2783 * host.
2785 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2786 const struct ndr_syntax_id *abstract_syntax,
2787 struct rpc_pipe_client **presult)
2789 NTSTATUS status;
2790 uint16_t port = 0;
2792 *presult = NULL;
2794 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 goto done;
2799 status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
2800 abstract_syntax, presult);
2802 done:
2803 return status;
2806 /********************************************************************
2807 Create a rpc pipe client struct, connecting to a unix domain socket
2808 ********************************************************************/
2809 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2810 const struct ndr_syntax_id *abstract_syntax,
2811 struct rpc_pipe_client **presult)
2813 struct rpc_pipe_client *result;
2814 struct sockaddr_un addr;
2815 NTSTATUS status;
2817 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2818 if (result == NULL) {
2819 return NT_STATUS_NO_MEMORY;
2822 result->transport_type = NCACN_UNIX_STREAM;
2824 result->abstract_syntax = *abstract_syntax;
2825 result->transfer_syntax = ndr_transfer_syntax;
2827 result->desthost = get_myname(result);
2828 result->srv_name_slash = talloc_asprintf_strupper_m(
2829 result, "\\\\%s", result->desthost);
2830 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2831 status = NT_STATUS_NO_MEMORY;
2832 goto fail;
2835 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2836 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2838 result->trans.sock.fd = socket(AF_UNIX, SOCK_STREAM, 0);
2839 if (result->trans.sock.fd == -1) {
2840 status = map_nt_error_from_unix(errno);
2841 goto fail;
2844 talloc_set_destructor(result, rpc_pipe_sock_destructor);
2846 ZERO_STRUCT(addr);
2847 addr.sun_family = AF_UNIX;
2848 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2850 if (sys_connect(result->trans.sock.fd,
2851 (struct sockaddr *)&addr) == -1) {
2852 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2853 strerror(errno)));
2854 close(result->trans.sock.fd);
2855 return map_nt_error_from_unix(errno);
2858 *presult = result;
2859 return NT_STATUS_OK;
2861 fail:
2862 TALLOC_FREE(result);
2863 return status;
2867 /****************************************************************************
2868 Open a named pipe over SMB to a remote server.
2870 * CAVEAT CALLER OF THIS FUNCTION:
2871 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2872 * so be sure that this function is called AFTER any structure (vs pointer)
2873 * assignment of the cli. In particular, libsmbclient does structure
2874 * assignments of cli, which invalidates the data in the returned
2875 * rpc_pipe_client if this function is called before the structure assignment
2876 * of cli.
2878 ****************************************************************************/
2880 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2881 const struct ndr_syntax_id *abstract_syntax,
2882 struct rpc_pipe_client **presult)
2884 struct rpc_pipe_client *result;
2885 int fnum;
2887 /* sanity check to protect against crashes */
2889 if ( !cli ) {
2890 return NT_STATUS_INVALID_HANDLE;
2893 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2894 if (result == NULL) {
2895 return NT_STATUS_NO_MEMORY;
2898 result->transport_type = NCACN_NP;
2900 result->trans.np.pipe_name = cli_get_pipe_name_from_iface(
2901 result, cli, abstract_syntax);
2902 if (result->trans.np.pipe_name == NULL) {
2903 DEBUG(1, ("Could not find pipe for interface\n"));
2904 TALLOC_FREE(result);
2905 return NT_STATUS_INVALID_PARAMETER;
2908 result->trans.np.cli = cli;
2909 result->abstract_syntax = *abstract_syntax;
2910 result->transfer_syntax = ndr_transfer_syntax;
2911 result->desthost = talloc_strdup(result, cli->desthost);
2912 result->srv_name_slash = talloc_asprintf_strupper_m(
2913 result, "\\\\%s", result->desthost);
2915 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2916 TALLOC_FREE(result);
2917 return NT_STATUS_NO_MEMORY;
2920 fnum = cli_nt_create(cli, result->trans.np.pipe_name,
2921 DESIRED_ACCESS_PIPE);
2922 if (fnum == -1) {
2923 DEBUG(1,("rpc_pipe_open_np: cli_nt_create failed on pipe %s "
2924 "to machine %s. Error was %s\n",
2925 result->trans.np.pipe_name, cli->desthost,
2926 cli_errstr(cli)));
2927 TALLOC_FREE(result);
2928 return cli_get_nt_error(cli);
2931 result->trans.np.fnum = fnum;
2933 DLIST_ADD(cli->pipe_list, result);
2934 talloc_set_destructor(result, rpc_pipe_destructor);
2936 *presult = result;
2937 return NT_STATUS_OK;
2940 /****************************************************************************
2941 Open a pipe to a remote server.
2942 ****************************************************************************/
2944 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2945 const struct ndr_syntax_id *interface,
2946 struct rpc_pipe_client **presult)
2948 if (ndr_syntax_id_equal(interface, &ndr_table_drsuapi.syntax_id)) {
2950 * We should have a better way to figure out this drsuapi
2951 * speciality...
2953 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2954 presult);
2957 return rpc_pipe_open_np(cli, interface, presult);
2960 /****************************************************************************
2961 Open a named pipe to an SMB server and bind anonymously.
2962 ****************************************************************************/
2964 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2965 const struct ndr_syntax_id *interface,
2966 struct rpc_pipe_client **presult)
2968 struct rpc_pipe_client *result;
2969 struct cli_pipe_auth_data *auth;
2970 NTSTATUS status;
2972 status = cli_rpc_pipe_open(cli, interface, &result);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 return status;
2977 status = rpccli_anon_bind_data(result, &auth);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2980 nt_errstr(status)));
2981 TALLOC_FREE(result);
2982 return status;
2986 * This is a bit of an abstraction violation due to the fact that an
2987 * anonymous bind on an authenticated SMB inherits the user/domain
2988 * from the enclosing SMB creds
2991 TALLOC_FREE(auth->user_name);
2992 TALLOC_FREE(auth->domain);
2994 auth->user_name = talloc_strdup(auth, cli->user_name);
2995 auth->domain = talloc_strdup(auth, cli->domain);
2997 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2998 TALLOC_FREE(result);
2999 return NT_STATUS_NO_MEMORY;
3002 status = rpc_pipe_bind(result, auth);
3003 if (!NT_STATUS_IS_OK(status)) {
3004 int lvl = 0;
3005 if (ndr_syntax_id_equal(interface,
3006 &ndr_table_dssetup.syntax_id)) {
3007 /* non AD domains just don't have this pipe, avoid
3008 * level 0 statement in that case - gd */
3009 lvl = 3;
3011 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3012 "%s failed with error %s\n",
3013 cli_get_pipe_name_from_iface(debug_ctx(), cli,
3014 interface),
3015 nt_errstr(status) ));
3016 TALLOC_FREE(result);
3017 return status;
3020 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3021 "%s and bound anonymously.\n", result->trans.np.pipe_name,
3022 cli->desthost ));
3024 *presult = result;
3025 return NT_STATUS_OK;
3028 /****************************************************************************
3029 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3030 ****************************************************************************/
3032 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3033 const struct ndr_syntax_id *interface,
3034 enum pipe_auth_type auth_type,
3035 enum pipe_auth_level auth_level,
3036 const char *domain,
3037 const char *username,
3038 const char *password,
3039 struct rpc_pipe_client **presult)
3041 struct rpc_pipe_client *result;
3042 struct cli_pipe_auth_data *auth;
3043 NTSTATUS status;
3045 status = cli_rpc_pipe_open(cli, interface, &result);
3046 if (!NT_STATUS_IS_OK(status)) {
3047 return status;
3050 status = rpccli_ntlmssp_bind_data(
3051 result, auth_type, auth_level, domain, username,
3052 cli->pwd.null_pwd ? NULL : password, &auth);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3055 nt_errstr(status)));
3056 goto err;
3059 status = rpc_pipe_bind(result, auth);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3062 nt_errstr(status) ));
3063 goto err;
3066 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3067 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3068 result->trans.np.pipe_name, cli->desthost,
3069 domain, username ));
3071 *presult = result;
3072 return NT_STATUS_OK;
3074 err:
3076 TALLOC_FREE(result);
3077 return status;
3080 /****************************************************************************
3081 External interface.
3082 Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3083 ****************************************************************************/
3085 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3086 const struct ndr_syntax_id *interface,
3087 enum pipe_auth_level auth_level,
3088 const char *domain,
3089 const char *username,
3090 const char *password,
3091 struct rpc_pipe_client **presult)
3093 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3094 interface,
3095 PIPE_AUTH_TYPE_NTLMSSP,
3096 auth_level,
3097 domain,
3098 username,
3099 password,
3100 presult);
3103 /****************************************************************************
3104 External interface.
3105 Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3106 ****************************************************************************/
3108 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3109 const struct ndr_syntax_id *interface,
3110 enum pipe_auth_level auth_level,
3111 const char *domain,
3112 const char *username,
3113 const char *password,
3114 struct rpc_pipe_client **presult)
3116 return cli_rpc_pipe_open_ntlmssp_internal(cli,
3117 interface,
3118 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3119 auth_level,
3120 domain,
3121 username,
3122 password,
3123 presult);
3126 /****************************************************************************
3127 Get a the schannel session key out of an already opened netlogon pipe.
3128 ****************************************************************************/
3129 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3130 struct cli_state *cli,
3131 const char *domain,
3132 uint32 *pneg_flags)
3134 uint32 sec_chan_type = 0;
3135 unsigned char machine_pwd[16];
3136 const char *machine_account;
3137 NTSTATUS status;
3139 /* Get the machine account credentials from secrets.tdb. */
3140 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3141 &sec_chan_type))
3143 DEBUG(0, ("get_schannel_session_key: could not fetch "
3144 "trust account password for domain '%s'\n",
3145 domain));
3146 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3149 status = rpccli_netlogon_setup_creds(netlogon_pipe,
3150 cli->desthost, /* server name */
3151 domain, /* domain */
3152 global_myname(), /* client name */
3153 machine_account, /* machine account name */
3154 machine_pwd,
3155 sec_chan_type,
3156 pneg_flags);
3158 if (!NT_STATUS_IS_OK(status)) {
3159 DEBUG(3, ("get_schannel_session_key_common: "
3160 "rpccli_netlogon_setup_creds failed with result %s "
3161 "to server %s, domain %s, machine account %s.\n",
3162 nt_errstr(status), cli->desthost, domain,
3163 machine_account ));
3164 return status;
3167 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3168 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3169 cli->desthost));
3170 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3173 return NT_STATUS_OK;;
3176 /****************************************************************************
3177 Open a netlogon pipe and get the schannel session key.
3178 Now exposed to external callers.
3179 ****************************************************************************/
3182 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3183 const char *domain,
3184 uint32 *pneg_flags,
3185 struct rpc_pipe_client **presult)
3187 struct rpc_pipe_client *netlogon_pipe = NULL;
3188 NTSTATUS status;
3190 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3191 &netlogon_pipe);
3192 if (!NT_STATUS_IS_OK(status)) {
3193 return status;
3196 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3197 pneg_flags);
3198 if (!NT_STATUS_IS_OK(status)) {
3199 TALLOC_FREE(netlogon_pipe);
3200 return status;
3203 *presult = netlogon_pipe;
3204 return NT_STATUS_OK;
3207 /****************************************************************************
3208 External interface.
3209 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3210 using session_key. sign and seal.
3211 ****************************************************************************/
3213 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3214 const struct ndr_syntax_id *interface,
3215 enum pipe_auth_level auth_level,
3216 const char *domain,
3217 const struct dcinfo *pdc,
3218 struct rpc_pipe_client **presult)
3220 struct rpc_pipe_client *result;
3221 struct cli_pipe_auth_data *auth;
3222 NTSTATUS status;
3224 status = cli_rpc_pipe_open(cli, interface, &result);
3225 if (!NT_STATUS_IS_OK(status)) {
3226 return status;
3229 status = rpccli_schannel_bind_data(result, domain, auth_level,
3230 pdc->sess_key, &auth);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3233 nt_errstr(status)));
3234 TALLOC_FREE(result);
3235 return status;
3238 status = rpc_pipe_bind(result, auth);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3241 "cli_rpc_pipe_bind failed with error %s\n",
3242 nt_errstr(status) ));
3243 TALLOC_FREE(result);
3244 return status;
3248 * The credentials on a new netlogon pipe are the ones we are passed
3249 * in - copy them over.
3251 result->dc = (struct dcinfo *)talloc_memdup(result, pdc, sizeof(*pdc));
3252 if (result->dc == NULL) {
3253 DEBUG(0, ("talloc failed\n"));
3254 TALLOC_FREE(result);
3255 return NT_STATUS_NO_MEMORY;
3258 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3259 "for domain %s "
3260 "and bound using schannel.\n",
3261 result->trans.np.pipe_name, cli->desthost, domain ));
3263 *presult = result;
3264 return NT_STATUS_OK;
3267 /****************************************************************************
3268 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3269 Fetch the session key ourselves using a temporary netlogon pipe. This
3270 version uses an ntlmssp auth bound netlogon pipe to get the key.
3271 ****************************************************************************/
3273 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3274 const char *domain,
3275 const char *username,
3276 const char *password,
3277 uint32 *pneg_flags,
3278 struct rpc_pipe_client **presult)
3280 struct rpc_pipe_client *netlogon_pipe = NULL;
3281 NTSTATUS status;
3283 status = cli_rpc_pipe_open_spnego_ntlmssp(
3284 cli, &ndr_table_netlogon.syntax_id, PIPE_AUTH_LEVEL_PRIVACY,
3285 domain, username, password, &netlogon_pipe);
3286 if (!NT_STATUS_IS_OK(status)) {
3287 return status;
3290 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3291 pneg_flags);
3292 if (!NT_STATUS_IS_OK(status)) {
3293 TALLOC_FREE(netlogon_pipe);
3294 return status;
3297 *presult = netlogon_pipe;
3298 return NT_STATUS_OK;
3301 /****************************************************************************
3302 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3303 Fetch the session key ourselves using a temporary netlogon pipe. This version
3304 uses an ntlmssp bind to get the session key.
3305 ****************************************************************************/
3307 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3308 const struct ndr_syntax_id *interface,
3309 enum pipe_auth_level auth_level,
3310 const char *domain,
3311 const char *username,
3312 const char *password,
3313 struct rpc_pipe_client **presult)
3315 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3316 struct rpc_pipe_client *netlogon_pipe = NULL;
3317 struct rpc_pipe_client *result = NULL;
3318 NTSTATUS status;
3320 status = get_schannel_session_key_auth_ntlmssp(
3321 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3322 if (!NT_STATUS_IS_OK(status)) {
3323 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3324 "key from server %s for domain %s.\n",
3325 cli->desthost, domain ));
3326 return status;
3329 status = cli_rpc_pipe_open_schannel_with_key(
3330 cli, interface, auth_level, domain, netlogon_pipe->dc,
3331 &result);
3333 /* Now we've bound using the session key we can close the netlog pipe. */
3334 TALLOC_FREE(netlogon_pipe);
3336 if (NT_STATUS_IS_OK(status)) {
3337 *presult = result;
3339 return status;
3342 /****************************************************************************
3343 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3344 Fetch the session key ourselves using a temporary netlogon pipe.
3345 ****************************************************************************/
3347 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3348 const struct ndr_syntax_id *interface,
3349 enum pipe_auth_level auth_level,
3350 const char *domain,
3351 struct rpc_pipe_client **presult)
3353 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3354 struct rpc_pipe_client *netlogon_pipe = NULL;
3355 struct rpc_pipe_client *result = NULL;
3356 NTSTATUS status;
3358 status = get_schannel_session_key(cli, domain, &neg_flags,
3359 &netlogon_pipe);
3360 if (!NT_STATUS_IS_OK(status)) {
3361 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3362 "key from server %s for domain %s.\n",
3363 cli->desthost, domain ));
3364 return status;
3367 status = cli_rpc_pipe_open_schannel_with_key(
3368 cli, interface, auth_level, domain, netlogon_pipe->dc,
3369 &result);
3371 /* Now we've bound using the session key we can close the netlog pipe. */
3372 TALLOC_FREE(netlogon_pipe);
3374 if (NT_STATUS_IS_OK(status)) {
3375 *presult = result;
3378 return NT_STATUS_OK;
3381 /****************************************************************************
3382 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3383 The idea is this can be called with service_princ, username and password all
3384 NULL so long as the caller has a TGT.
3385 ****************************************************************************/
3387 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3388 const struct ndr_syntax_id *interface,
3389 enum pipe_auth_level auth_level,
3390 const char *service_princ,
3391 const char *username,
3392 const char *password,
3393 struct rpc_pipe_client **presult)
3395 #ifdef HAVE_KRB5
3396 struct rpc_pipe_client *result;
3397 struct cli_pipe_auth_data *auth;
3398 NTSTATUS status;
3400 status = cli_rpc_pipe_open(cli, interface, &result);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 return status;
3405 status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3406 username, password, &auth);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3409 nt_errstr(status)));
3410 TALLOC_FREE(result);
3411 return status;
3414 status = rpc_pipe_bind(result, auth);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3417 "with error %s\n", nt_errstr(status)));
3418 TALLOC_FREE(result);
3419 return status;
3422 *presult = result;
3423 return NT_STATUS_OK;
3424 #else
3425 DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3426 return NT_STATUS_NOT_IMPLEMENTED;
3427 #endif
3430 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3431 struct rpc_pipe_client *cli,
3432 DATA_BLOB *session_key)
3434 if (!session_key || !cli) {
3435 return NT_STATUS_INVALID_PARAMETER;
3438 if (!cli->auth) {
3439 return NT_STATUS_INVALID_PARAMETER;
3442 switch (cli->auth->auth_type) {
3443 case PIPE_AUTH_TYPE_SCHANNEL:
3444 *session_key = data_blob_talloc(mem_ctx,
3445 cli->auth->a_u.schannel_auth->sess_key, 16);
3446 break;
3447 case PIPE_AUTH_TYPE_NTLMSSP:
3448 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3449 *session_key = data_blob_talloc(mem_ctx,
3450 cli->auth->a_u.ntlmssp_state->session_key.data,
3451 cli->auth->a_u.ntlmssp_state->session_key.length);
3452 break;
3453 case PIPE_AUTH_TYPE_KRB5:
3454 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3455 *session_key = data_blob_talloc(mem_ctx,
3456 cli->auth->a_u.kerberos_auth->session_key.data,
3457 cli->auth->a_u.kerberos_auth->session_key.length);
3458 break;
3459 case PIPE_AUTH_TYPE_NONE:
3460 default:
3461 return NT_STATUS_NO_USER_SESSION_KEY;
3464 return NT_STATUS_OK;