cli_pipe.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,128 行 · 第 1/5 页

C
2,128
字号
/******************************************************************* Creates a DCE/RPC bind authentication response. This is the packet that is sent back to the server once we have received a BIND-ACK, to finish the third leg of the authentication handshake. ********************************************************************/static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,				uint32 rpc_call_id,				enum pipe_auth_type auth_type,				enum pipe_auth_level auth_level,				DATA_BLOB *pauth_blob,				prs_struct *rpc_out){	RPC_HDR hdr;	RPC_HDR_AUTH hdr_auth;	uint32 pad = 0;	/* Create the request RPC_HDR */	init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,		     RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,		     pauth_blob->length );		/* Marshall it. */	if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {		DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));		return NT_STATUS_NO_MEMORY;	}	/*		I'm puzzled about this - seems to violate the DCE RPC auth rules,		about padding - shouldn't this pad to length 8 ? JRA.	*/	/* 4 bytes padding. */	if (!prs_uint32("pad", rpc_out, 0, &pad)) {		DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));		return NT_STATUS_NO_MEMORY;	}	/* Create the request RPC_HDR_AUTHA */	init_rpc_hdr_auth(&hdr_auth,			map_pipe_auth_type_to_rpc_auth_type(auth_type),			auth_level, 0, 1);	if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {		DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));		return NT_STATUS_NO_MEMORY;	}	/*	 * Append the auth data to the outgoing buffer.	 */	if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {		DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));		return NT_STATUS_NO_MEMORY;	}	return NT_STATUS_OK;}/**************************************************************************** Create and send the third packet in an RPC auth.****************************************************************************/static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,				RPC_HDR *phdr,				prs_struct *rbuf,				uint32 rpc_call_id,				enum pipe_auth_type auth_type,				enum pipe_auth_level auth_level){	DATA_BLOB server_response = data_blob(NULL,0);	DATA_BLOB client_reply = data_blob(NULL,0);	RPC_HDR_AUTH hdr_auth;	NTSTATUS nt_status;	prs_struct rpc_out;	ssize_t ret;	if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {		return NT_STATUS_INVALID_PARAMETER;	}	/* Process the returned NTLMSSP blob first. */	if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {		return NT_STATUS_INVALID_PARAMETER;	}	if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {		return NT_STATUS_INVALID_PARAMETER;	}	/* TODO - check auth_type/auth_level match. */	server_response = data_blob(NULL, phdr->auth_len);	prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);		nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,				   server_response,				   &client_reply);		if (!NT_STATUS_IS_OK(nt_status)) {		DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));		return nt_status;	}	prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);	nt_status = create_rpc_bind_auth3(cli, rpc_call_id,				auth_type, auth_level,				&client_reply, &rpc_out);	if (!NT_STATUS_IS_OK(nt_status)) {		prs_mem_free(&rpc_out);		data_blob_free(&client_reply);		data_blob_free(&server_response);		return nt_status;	}	/* 8 here is named pipe message mode. */	ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,				(size_t)prs_offset(&rpc_out));	if (ret != (ssize_t)prs_offset(&rpc_out)) {		DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));		prs_mem_free(&rpc_out);		data_blob_free(&client_reply);		data_blob_free(&server_response);		return cli_get_nt_error(cli->cli);	}	DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "		"fnum 0x%x sent auth3 response ok.\n",		cli->cli->desthost,		cli->pipe_name,		(unsigned int)cli->fnum));	prs_mem_free(&rpc_out);	data_blob_free(&client_reply);	data_blob_free(&server_response);	return NT_STATUS_OK;}/******************************************************************* Creates a DCE/RPC bind alter context authentication request which may contain a spnego auth blobl ********************************************************************/static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,					RPC_IFACE *abstract,					RPC_IFACE *transfer,					enum pipe_auth_level auth_level,					const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */					prs_struct *rpc_out){	RPC_HDR_AUTH hdr_auth;	prs_struct auth_info;	NTSTATUS ret = NT_STATUS_OK;	ZERO_STRUCT(hdr_auth);	prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);	/* We may change the pad length before marshalling. */	init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);	if (pauth_blob->length) {		if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {			prs_mem_free(&auth_info);			return NT_STATUS_NO_MEMORY;		}	}	ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,						rpc_out, 						rpc_call_id,						abstract,						transfer,						&hdr_auth,						&auth_info);	prs_mem_free(&auth_info);	return ret;}/******************************************************************* Third leg of the SPNEGO bind mechanism - sends alter context PDU and gets a response. ********************************************************************/static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,                                RPC_HDR *phdr,                                prs_struct *rbuf,                                uint32 rpc_call_id,				RPC_IFACE *abstract,				RPC_IFACE *transfer,                                enum pipe_auth_type auth_type,                                enum pipe_auth_level auth_level){	DATA_BLOB server_spnego_response = data_blob(NULL,0);	DATA_BLOB server_ntlm_response = data_blob(NULL,0);	DATA_BLOB client_reply = data_blob(NULL,0);	DATA_BLOB tmp_blob = data_blob(NULL, 0);	RPC_HDR_AUTH hdr_auth;	NTSTATUS nt_status;	prs_struct rpc_out;	if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {		return NT_STATUS_INVALID_PARAMETER;	}	/* Process the returned NTLMSSP blob first. */	if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {		return NT_STATUS_INVALID_PARAMETER;	}	if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {		return NT_STATUS_INVALID_PARAMETER;	}	server_spnego_response = data_blob(NULL, phdr->auth_len);	prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);		/* The server might give us back two challenges - tmp_blob is for the second. */	if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {		data_blob_free(&server_spnego_response);		data_blob_free(&server_ntlm_response);		data_blob_free(&tmp_blob);		return NT_STATUS_INVALID_PARAMETER;	}	/* We're finished with the server spnego response and the tmp_blob. */	data_blob_free(&server_spnego_response);	data_blob_free(&tmp_blob);	nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,				   server_ntlm_response,				   &client_reply);		/* Finished with the server_ntlm response */	data_blob_free(&server_ntlm_response);	if (!NT_STATUS_IS_OK(nt_status)) {		DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));		data_blob_free(&client_reply);		return nt_status;	}	/* SPNEGO wrap the client reply. */	tmp_blob = spnego_gen_auth(client_reply);	data_blob_free(&client_reply);	client_reply = tmp_blob;	tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */	/* Now prepare the alter context pdu. */	prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);	nt_status = create_rpc_alter_context(rpc_call_id,						abstract,						transfer,						auth_level,						&client_reply,						&rpc_out);	data_blob_free(&client_reply);	if (!NT_STATUS_IS_OK(nt_status)) {		prs_mem_free(&rpc_out);		return nt_status;	}	/* Initialize the returning data struct. */	prs_mem_free(rbuf);	prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);	nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);	if (!NT_STATUS_IS_OK(nt_status)) {		prs_mem_free(&rpc_out);		return nt_status;	}	prs_mem_free(&rpc_out);	/* Get the auth blob from the reply. */	if(!smb_io_rpc_hdr("rpc_hdr   ", phdr, rbuf, 0)) {		DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));		return NT_STATUS_BUFFER_TOO_SMALL;	}	if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {		return NT_STATUS_INVALID_PARAMETER;	}	if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {		return NT_STATUS_INVALID_PARAMETER;	}	server_spnego_response = data_blob(NULL, phdr->auth_len);	prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);	/* Check we got a valid auth response. */	if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) {		data_blob_free(&server_spnego_response);		data_blob_free(&tmp_blob);		return NT_STATUS_INVALID_PARAMETER;	}	data_blob_free(&server_spnego_response);	data_blob_free(&tmp_blob);	DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "		"remote machine %s pipe %s fnum 0x%x.\n",		cli->cli->desthost,		cli->pipe_name,		(unsigned int)cli->fnum));	return NT_STATUS_OK;}/**************************************************************************** Do an rpc bind.****************************************************************************/static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,			enum pipe_auth_type auth_type,			enum pipe_auth_level auth_level){	RPC_HDR hdr;	RPC_HDR_BA hdr_ba;	RPC_IFACE abstract;	RPC_IFACE transfer;	prs_struct rpc_out;	prs_struct rbuf;	uint32 rpc_call_id;	NTSTATUS status;	DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",		(unsigned int)cli->fnum,		cli->pipe_name,		(unsigned int)auth_type,		(unsigned int)auth_level ));	if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {		return NT_STATUS_INVALID_PARAMETER;	}	prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);	rpc_call_id = get_rpc_call_id();	/* Marshall the outgoing data. */	status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,				&abstract, &transfer,				auth_type,				auth_level);	if (!NT_STATUS_IS_OK(status)) {		prs_mem_free(&rpc_out);		return status;	}	/* Initialize the incoming data struct. */	prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);	/* send data on \PIPE\.  receive a response */	status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);	if (!NT_STATUS_IS_OK(status)) {		prs_mem_free(&rpc_out);		return status;	}	prs_mem_free(&rpc_out);	DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "		"fnum 0x%x bind request returned ok.\n",		cli->cli->desthost,		cli->pipe_name,		(unsigned int)cli->fnum));	/* Unmarshall the RPC header */	if(!smb_io_rpc_hdr("hdr"   , &hdr, &rbuf, 0)) {		DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));		prs_mem_free(&rbuf);		return NT_STATUS_BUFFER_TOO_SMALL;	}	if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {		DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));		prs_mem_free(&rbuf);		return NT_STATUS_BUFFER_TOO_SMALL;	}	if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {		DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));		prs_mem_free(&rbuf);		return NT_STATUS_BUFFER_TOO_SMALL;	}	cli->max_xmit_frag = hdr_ba.bba.max_tsize;	cli->max_recv_frag = hdr_ba.bba.max_rsize;	/* For authenticated binds we may need to do 3 or 4 leg binds. */	switch(auth_type) {		case PIPE_AUTH_TYPE_NONE:		case PIPE_AUTH_TYPE_SCHANNEL:			/* Bind complete. */			break;		case PIPE_AUTH_TYPE_NTLMSSP:			/* Need to send AUTH3 packet - no reply. */			status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,						auth_type, auth_level);			if (!NT_STATUS_IS_OK(status)) {				prs_mem_free(&rbuf);				return status;			}			break;		case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:			/* Need to send alter context request and reply. */			status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,						&abstract, &transfer,						auth_type, auth_level);			if 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?