cli_pipe.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,128 行 · 第 1/5 页
C
2,128 行
(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); return status; } break; case PIPE_AUTH_LEVEL_INTEGRITY: /* Data is signed. */ status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state, (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, data_and_pad_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); return status; } break; default: /* Can't happen. */ smb_panic("bad auth level"); /* Notreached. */ return NT_STATUS_INVALID_PARAMETER; } /* Finally marshall the blob. */ if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) { DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n", (unsigned int)NTLMSSP_SIG_SIZE)); data_blob_free(&auth_blob); return NT_STATUS_NO_MEMORY; } data_blob_free(&auth_blob); return NT_STATUS_OK;}/******************************************************************* Create and add the schannel sign/seal auth header and data. ********************************************************************/static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, RPC_HDR *phdr, uint32 ss_padding_len, prs_struct *outgoing_pdu){ RPC_HDR_AUTH auth_info; RPC_AUTH_SCHANNEL_CHK verf; struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth; char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; if (!sas) { return NT_STATUS_INVALID_PARAMETER; } /* Init and marshall the auth header. */ init_rpc_hdr_auth(&auth_info, map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type), cli->auth.auth_level, ss_padding_len, 1 /* context id. */); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) { DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n")); return NT_STATUS_NO_MEMORY; } switch (cli->auth.auth_level) { case PIPE_AUTH_LEVEL_PRIVACY: case PIPE_AUTH_LEVEL_INTEGRITY: DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", sas->seq_num)); schannel_encode(sas, cli->auth.auth_level, SENDER_IS_INITIATOR, &verf, data_p, data_and_pad_len); sas->seq_num++; break; default: /* Can't happen. */ smb_panic("bad auth level"); /* Notreached. */ return NT_STATUS_INVALID_PARAMETER; } /* Finally marshall the blob. */ smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &verf, outgoing_pdu, 0); return NT_STATUS_OK;}/******************************************************************* Calculate how much data we're going to send in this packet, also work out any sign/seal padding length. ********************************************************************/static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, uint32 data_left, uint16 *p_frag_len, uint16 *p_auth_len, uint32 *p_ss_padding){ uint32 data_space, data_len; switch (cli->auth.auth_level) { case PIPE_AUTH_LEVEL_NONE: case PIPE_AUTH_LEVEL_CONNECT: data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN; data_len = MIN(data_space, data_left); *p_ss_padding = 0; *p_auth_len = 0; *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len; return data_len; case PIPE_AUTH_LEVEL_INTEGRITY: case PIPE_AUTH_LEVEL_PRIVACY: /* Treat the same for all authenticated rpc requests. */ switch(cli->auth.auth_type) { case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: case PIPE_AUTH_TYPE_NTLMSSP: *p_auth_len = NTLMSSP_SIG_SIZE; break; case PIPE_AUTH_TYPE_SCHANNEL: *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; break; default: smb_panic("bad auth type"); break; } data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - *p_auth_len; data_len = MIN(data_space, data_left); if (data_len % 8) { *p_ss_padding = 8 - (data_len % 8); } *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */ data_len + *p_ss_padding + /* data plus padding. */ RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */ return data_len; default: smb_panic("bad auth level"); /* Notreached. */ return 0; }}/******************************************************************* External interface. Does an rpc request on a pipe. Incoming data is NDR encoded in in_data. Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's and deals with signing/sealing details. ********************************************************************/NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli, uint8 op_num, prs_struct *in_data, prs_struct *out_data){ NTSTATUS ret; uint32 data_left = prs_offset(in_data); uint32 alloc_hint = prs_offset(in_data); uint32 data_sent_thistime = 0; uint32 current_data_offset = 0; uint32 call_id = get_rpc_call_id(); char pad[8]; prs_struct outgoing_pdu; memset(pad, '\0', 8); if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) { /* Server is screwed up ! */ return NT_STATUS_INVALID_PARAMETER; } prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL); while (1) { RPC_HDR hdr; RPC_HDR_REQ hdr_req; uint16 auth_len = 0; uint16 frag_len = 0; uint8 flags = 0; uint32 ss_padding = 0; data_sent_thistime = calculate_data_len_tosend(cli, data_left, &frag_len, &auth_len, &ss_padding); if (current_data_offset == 0) { flags = RPC_FLG_FIRST; } if (data_sent_thistime == data_left) { flags |= RPC_FLG_LAST; } /* Create and marshall the header and request header. */ init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len); if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) { prs_mem_free(&outgoing_pdu); return NT_STATUS_NO_MEMORY; } /* Create the rpc request RPC_HDR_REQ */ init_rpc_hdr_req(&hdr_req, alloc_hint, op_num); if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) { prs_mem_free(&outgoing_pdu); return NT_STATUS_NO_MEMORY; } /* Copy in the data, plus any ss padding. */ if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) { prs_mem_free(&outgoing_pdu); return NT_STATUS_NO_MEMORY; } /* Copy the sign/seal padding data. */ if (ss_padding) { if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) { prs_mem_free(&outgoing_pdu); return NT_STATUS_NO_MEMORY; } } /* Generate any auth sign/seal and add the auth footer. */ if (auth_len) { switch (cli->auth.auth_type) { case PIPE_AUTH_TYPE_NONE: break; case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&outgoing_pdu); return ret; } break; case PIPE_AUTH_TYPE_SCHANNEL: ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&outgoing_pdu); return ret; } break; default: smb_panic("bad auth type"); break; /* notreached */ } } /* Actually send the packet. */ if (flags & RPC_FLG_LAST) { /* Last packet - send the data, get the reply and return. */ ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE); prs_mem_free(&outgoing_pdu); if (DEBUGLEVEL >= 50) { pstring dump_name; /* Also capture received data */ slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d", dyn_LOGFILEBASE, cli->pipe_name, op_num); prs_dump(dump_name, op_num, out_data); } return ret; } else { /* More packets to come - write and continue. */ ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */ prs_data_p(&outgoing_pdu), (off_t)0, (size_t)hdr.frag_len); if (num_written != hdr.frag_len) { prs_mem_free(&outgoing_pdu); return cli_get_nt_error(cli->cli); } } current_data_offset += data_sent_thistime; data_left -= data_sent_thistime; /* Reset the marshalling position back to zero. */ if (!prs_set_offset(&outgoing_pdu, 0)) { prs_mem_free(&outgoing_pdu); return NT_STATUS_NO_MEMORY; } }}#if 0/**************************************************************************** Set the handle state.****************************************************************************/static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli, const char *pipe_name, uint16 device_state){ BOOL state_set = False; char param[2]; uint16 setup[2]; /* only need 2 uint16 setup parameters */ char *rparam = NULL; char *rdata = NULL; uint32 rparam_len, rdata_len; if (pipe_name == NULL) return False; DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n", cli->fnum, pipe_name, device_state)); /* create parameters: device state */ SSVAL(param, 0, device_state); /* create setup parameters. */ setup[0] = 0x0001; setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */ /* send the data on \PIPE\ */ if (cli_api_pipe(cli->cli, "\\PIPE\\", setup, 2, 0, /* setup, length, max */ param, 2, 0, /* param, length, max */ NULL, 0, 1024, /* data, length, max */ &rparam, &rparam_len, /* return param, length */ &rdata, &rdata_len)) /* return data, length */ { DEBUG(5, ("Set Handle state: return OK\n")); state_set = True; } SAFE_FREE(rparam); SAFE_FREE(rdata); return state_set;}#endif/**************************************************************************** Check the rpc bind acknowledge response.****************************************************************************/static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer){ if ( pipe_idx >= PI_MAX_PIPES ) { DEBUG(0,("valid_pipe_name: Programmer error! Invalid pipe index [%d]\n", pipe_idx)); return False; } DEBUG(5,("Bind Abstract Syntax: ")); dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax, sizeof(pipe_names[pipe_idx].abstr_syntax)); DEBUG(5,("Bind Transfer Syntax: ")); dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax, sizeof(pipe_names[pipe_idx].trans_syntax)); /* copy the required syntaxes out so we can do the right bind */ *transfer = pipe_names[pipe_idx].trans_syntax; *abstract = pipe_names[pipe_idx].abstr_syntax; return True;}/**************************************************************************** Check the rpc bind acknowledge response.****************************************************************************/static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer){ if ( hdr_ba->addr.len == 0) { DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)")); }# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */ if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) && !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) ) { DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n", pipe_names[i].server_pipe ,hdr_ba->addr.str)); return False; } DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe )); if (pipe_names[pipe_idx].server_pipe == NULL) { DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str)); return False; }#endif /* JERRY */ /* check the transfer syntax */ if ((hdr_ba->transfer.version != transfer->version) || (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) { DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n")); return False; } if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) { DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n", hdr_ba->res.num_results, hdr_ba->res.reason)); } DEBUG(5,("check_bind_response: accepted!\n")); return True;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?