📄 srv_pipe.c
字号:
/* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * Almost completely rewritten by (C) Jeremy Allison 2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* this module apparently provides an implementation of DCE/RPC over a * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC * documentation are available (in on-line form) from the X-Open group. * * this module should provide a level of abstraction between SMB * and DCE/RPC, while minimising the amount of mallocs, unnecessary * data copies, and network traffic. * */#include "includes.h"extern struct pipe_id_info pipe_names[];extern struct current_user current_user;#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_SRVstatic void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth){ AUTH_NTLMSSP_STATE *a = auth->a_u.auth_ntlmssp_state; if (a) { auth_ntlmssp_end(&a); } auth->a_u.auth_ntlmssp_state = NULL;}/******************************************************************* Generate the next PDU to be returned from the data in p->rdata. Handle NTLMSSP. ********************************************************************/static BOOL create_next_pdu_ntlmssp(pipes_struct *p){ RPC_HDR_RESP hdr_resp; uint32 ss_padding_len = 0; uint32 data_space_available; uint32 data_len_left; uint32 data_len; prs_struct outgoing_pdu; NTSTATUS status; DATA_BLOB auth_blob; RPC_HDR_AUTH auth_info; uint8 auth_type, auth_level; AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if(p->fault_state) { setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); /* Change the incoming request header to a response. */ p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; } else { p->hdr.flags = 0; } /* * Work out how much we can fit in a single PDU. */ data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* * Ensure there really is data left to send. */ if(!data_len_left) { DEBUG(0,("create_next_pdu_ntlmssp: no data left to send !\n")); return False; } data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - NTLMSSP_SIG_SIZE; /* * The amount we send is the minimum of the available * space and the amount left to send. */ data_len = MIN(data_len_left, data_space_available); /* * Set up the alloc hint. This should be the data left to * send. */ hdr_resp.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. */ if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; if (data_len_left % 8) { ss_padding_len = 8 - (data_len_left % 8); DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n", ss_padding_len )); } } /* * Set up the header lengths. */ p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + NTLMSSP_SIG_SIZE; p->hdr.auth_len = NTLMSSP_SIG_SIZE; /* * Init the parse struct to point at the outgoing * data. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* Copy the sign/seal padding data. */ if (ss_padding_len) { char pad[8]; memset(pad, '\0', 8); if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); prs_mem_free(&outgoing_pdu); return False; } } /* Now write out the auth header and null blob. */ if (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) { auth_type = RPC_NTLMSSP_AUTH_TYPE; } else { auth_type = RPC_SPNEGO_AUTH_TYPE; } if (p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY) { auth_level = RPC_AUTH_LEVEL_PRIVACY; } else { auth_level = RPC_AUTH_LEVEL_INTEGRITY; } init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1 /* context id. */); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Generate the sign blob. */ switch (p->auth.auth_level) { case PIPE_AUTH_LEVEL_PRIVACY: /* Data portion is encrypted. */ status = ntlmssp_seal_packet(a->ntlmssp_state, (unsigned char *)prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, data_len + ss_padding_len, (unsigned char *)prs_data_p(&outgoing_pdu), (size_t)prs_offset(&outgoing_pdu), &auth_blob); if (!NT_STATUS_IS_OK(status)) { data_blob_free(&auth_blob); prs_mem_free(&outgoing_pdu); return False; } break; case PIPE_AUTH_LEVEL_INTEGRITY: /* Data is signed. */ status = ntlmssp_sign_packet(a->ntlmssp_state, (unsigned char *)prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, data_len + ss_padding_len, (unsigned char *)prs_data_p(&outgoing_pdu), (size_t)prs_offset(&outgoing_pdu), &auth_blob); if (!NT_STATUS_IS_OK(status)) { data_blob_free(&auth_blob); prs_mem_free(&outgoing_pdu); return False; } break; default: prs_mem_free(&outgoing_pdu); return False; } /* Append the auth blob. */ if (!prs_copy_data_in(&outgoing_pdu, (char *)auth_blob.data, NTLMSSP_SIG_SIZE)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes auth blob.\n", (unsigned int)NTLMSSP_SIG_SIZE)); data_blob_free(&auth_blob); prs_mem_free(&outgoing_pdu); return False; } data_blob_free(&auth_blob); /* * Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True;}/******************************************************************* Generate the next PDU to be returned from the data in p->rdata. Return an schannel authenticated fragment. ********************************************************************/static BOOL create_next_pdu_schannel(pipes_struct *p){ RPC_HDR_RESP hdr_resp; uint32 ss_padding_len = 0; uint32 data_len; uint32 data_space_available; uint32 data_len_left; prs_struct outgoing_pdu; uint32 data_pos; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if(p->fault_state) { setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); /* Change the incoming request header to a response. */ p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; } else { p->hdr.flags = 0; } /* * Work out how much we can fit in a single PDU. */ data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* * Ensure there really is data left to send. */ if(!data_len_left) { DEBUG(0,("create_next_pdu_schannel: no data left to send !\n")); return False; } data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; /* * The amount we send is the minimum of the available * space and the amount left to send. */ data_len = MIN(data_len_left, data_space_available); /* * Set up the alloc hint. This should be the data left to * send. */ hdr_resp.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. */ if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; if (data_len_left % 8) { ss_padding_len = 8 - (data_len_left % 8); DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n", ss_padding_len )); } } p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; p->hdr.auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; /* * Init the parse struct to point at the outgoing * data. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Store the current offset. */ data_pos = prs_offset(&outgoing_pdu); /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { DEBUG(0,("create_next_pdu_schannel: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* Copy the sign/seal padding data. */ if (ss_padding_len) { char pad[8]; memset(pad, '\0', 8); if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); prs_mem_free(&outgoing_pdu); return False; } } { /* * Schannel processing. */ char *data; RPC_HDR_AUTH auth_info; RPC_AUTH_SCHANNEL_CHK verf; data = prs_data_p(&outgoing_pdu) + data_pos; /* Check it's the type of reply we were expecting to decode */ init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY ? RPC_AUTH_LEVEL_PRIVACY : RPC_AUTH_LEVEL_INTEGRITY, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } schannel_encode(p->auth.a_u.schannel_auth, p->auth.auth_level, SENDER_IS_ACCEPTOR, &verf, data, data_len + ss_padding_len); if (!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &verf, &outgoing_pdu, 0)) { prs_mem_free(&outgoing_pdu); return False; } p->auth.a_u.schannel_auth->seq_num++; } /* * Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True;}/******************************************************************* Generate the next PDU to be returned from the data in p->rdata. No authentication done.********************************************************************/static BOOL create_next_pdu_noauth(pipes_struct *p){ RPC_HDR_RESP hdr_resp; uint32 data_len; uint32 data_space_available; uint32 data_len_left; prs_struct outgoing_pdu; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if(p->fault_state) { setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -