cli_pipe.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,128 行 · 第 1/5 页
C
2,128 行
"PDU data format is big-endian.\n", cli->cli->desthost, cli->pipe_name, (unsigned int)cli->fnum)); prs_set_endian_data(rbuf, RPC_BIG_ENDIAN); } else { /* Check endianness on subsequent packets. */ if (current_pdu.bigendian_data != rbuf->bigendian_data) { DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n", rbuf->bigendian_data ? "big" : "little", current_pdu.bigendian_data ? "big" : "little" )); ret = NT_STATUS_INVALID_PARAMETER; goto err; } } } /* Now copy the data portion out of the pdu into rbuf. */ if (!prs_force_grow(rbuf, ret_data_len)) { ret = NT_STATUS_NO_MEMORY; goto err; } memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len); current_rbuf_offset += ret_data_len; /* See if we've finished with all the data in current_pdu yet ? */ ret = cli_pipe_reset_current_pdu(cli, &rhdr, ¤t_pdu); if (!NT_STATUS_IS_OK(ret)) { goto err; } if (rhdr.flags & RPC_FLG_LAST) { break; /* We're done. */ } } DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n", cli->cli->desthost, cli->pipe_name, (unsigned int)cli->fnum, (unsigned int)prs_data_size(rbuf) )); prs_mem_free(¤t_pdu); return NT_STATUS_OK; err: prs_mem_free(¤t_pdu); prs_mem_free(rbuf); return ret;}/******************************************************************* Creates krb5 auth bind. ********************************************************************/static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli, enum pipe_auth_level auth_level, RPC_HDR_AUTH *pauth_out, prs_struct *auth_data){#ifdef HAVE_KRB5 int ret; struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth; DATA_BLOB tkt = data_blob(NULL, 0); DATA_BLOB tkt_wrapped = data_blob(NULL, 0); /* We may change the pad length before marshalling. */ init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1); DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n", a->service_principal )); /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */ ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt, &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED); if (ret) { DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s " "failed with %s\n", a->service_principal, error_message(ret) )); data_blob_free(&tkt); prs_mem_free(auth_data); return NT_STATUS_INVALID_PARAMETER; } /* wrap that up in a nice GSS-API wrapping */ tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); data_blob_free(&tkt); /* Auth len in the rpc header doesn't include auth_header. */ if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) { data_blob_free(&tkt_wrapped); prs_mem_free(auth_data); return NT_STATUS_NO_MEMORY; } DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n")); dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length); data_blob_free(&tkt_wrapped); return NT_STATUS_OK;#else return NT_STATUS_INVALID_PARAMETER;#endif}/******************************************************************* Creates SPNEGO NTLMSSP auth bind. ********************************************************************/static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli, enum pipe_auth_level auth_level, RPC_HDR_AUTH *pauth_out, prs_struct *auth_data){ NTSTATUS nt_status; DATA_BLOB null_blob = data_blob(NULL, 0); DATA_BLOB request = data_blob(NULL, 0); DATA_BLOB spnego_msg = data_blob(NULL, 0); /* We may change the pad length before marshalling. */ init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1); DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n")); nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, null_blob, &request); if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { data_blob_free(&request); prs_mem_free(auth_data); return nt_status; } /* Wrap this in SPNEGO. */ spnego_msg = gen_negTokenInit(OID_NTLMSSP, request); data_blob_free(&request); /* Auth len in the rpc header doesn't include auth_header. */ if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) { data_blob_free(&spnego_msg); prs_mem_free(auth_data); return NT_STATUS_NO_MEMORY; } DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n")); dump_data(5, (const char *)spnego_msg.data, spnego_msg.length); data_blob_free(&spnego_msg); return NT_STATUS_OK;}/******************************************************************* Creates NTLMSSP auth bind. ********************************************************************/static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli, enum pipe_auth_level auth_level, RPC_HDR_AUTH *pauth_out, prs_struct *auth_data){ NTSTATUS nt_status; DATA_BLOB null_blob = data_blob(NULL, 0); DATA_BLOB request = data_blob(NULL, 0); /* We may change the pad length before marshalling. */ init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1); DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n")); nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, null_blob, &request); if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { data_blob_free(&request); prs_mem_free(auth_data); return nt_status; } /* Auth len in the rpc header doesn't include auth_header. */ if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) { data_blob_free(&request); prs_mem_free(auth_data); return NT_STATUS_NO_MEMORY; } DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n")); dump_data(5, (const char *)request.data, request.length); data_blob_free(&request); return NT_STATUS_OK;}/******************************************************************* Creates schannel auth bind. ********************************************************************/static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli, enum pipe_auth_level auth_level, RPC_HDR_AUTH *pauth_out, prs_struct *auth_data){ RPC_AUTH_SCHANNEL_NEG schannel_neg; /* We may change the pad length before marshalling. */ init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1); /* Use lp_workgroup() if domain not specified */ if (!cli->domain || !cli->domain[0]) { cli->domain = lp_workgroup(); } init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname()); /* * Now marshall the data into the auth parse_struct. */ if(!smb_io_rpc_auth_schannel_neg("schannel_neg", &schannel_neg, auth_data, 0)) { DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n")); prs_mem_free(auth_data); return NT_STATUS_NO_MEMORY; } return NT_STATUS_OK;}/******************************************************************* Creates the internals of a DCE/RPC bind request or alter context PDU. ********************************************************************/static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type, prs_struct *rpc_out, uint32 rpc_call_id, RPC_IFACE *abstract, RPC_IFACE *transfer, RPC_HDR_AUTH *phdr_auth, prs_struct *pauth_info){ RPC_HDR hdr; RPC_HDR_RB hdr_rb; RPC_CONTEXT rpc_ctx; uint16 auth_len = prs_offset(pauth_info); uint8 ss_padding_len = 0; uint16 frag_len = 0; /* create the RPC context. */ init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer); /* create the bind request RPC_HDR_RB */ init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx); /* Start building the frag length. */ frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb); /* Do we need to pad ? */ if (auth_len) { uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb); if (data_len % 8) { ss_padding_len = 8 - (data_len % 8); phdr_auth->auth_pad_len = ss_padding_len; } frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len; } /* Create the request RPC_HDR */ init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len); /* Marshall the RPC header */ if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n")); return NT_STATUS_NO_MEMORY; } /* Marshall the bind request data */ if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n")); return NT_STATUS_NO_MEMORY; } /* * Grow the outgoing buffer to store any auth info. */ if(auth_len != 0) { if (ss_padding_len) { char pad[8]; memset(pad, '\0', 8); if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n")); return NT_STATUS_NO_MEMORY; } } if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n")); return NT_STATUS_NO_MEMORY; } if(!prs_append_prs_data( rpc_out, pauth_info)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n")); return NT_STATUS_NO_MEMORY; } } return NT_STATUS_OK;}/******************************************************************* Creates a DCE/RPC bind request. ********************************************************************/static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, prs_struct *rpc_out, uint32 rpc_call_id, RPC_IFACE *abstract, RPC_IFACE *transfer, enum pipe_auth_type auth_type, enum pipe_auth_level auth_level){ 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); switch (auth_type) { case PIPE_AUTH_TYPE_SCHANNEL: ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&auth_info); return ret; } break; case PIPE_AUTH_TYPE_NTLMSSP: ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&auth_info); return ret; } break; case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&auth_info); return ret; } break; case PIPE_AUTH_TYPE_KRB5: ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info); if (!NT_STATUS_IS_OK(ret)) { prs_mem_free(&auth_info); return ret; } break; case PIPE_AUTH_TYPE_NONE: break; default: /* "Can't" happen. */ return NT_STATUS_INVALID_INFO_CLASS; } ret = create_bind_or_alt_ctx_internal(RPC_BIND, rpc_out, rpc_call_id, abstract, transfer, &hdr_auth, &auth_info); prs_mem_free(&auth_info); return ret;}/******************************************************************* Create and add the NTLMSSP sign/seal auth header and data. ********************************************************************/static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, RPC_HDR *phdr, uint32 ss_padding_len, prs_struct *outgoing_pdu){ RPC_HDR_AUTH auth_info; NTSTATUS status; DATA_BLOB auth_blob = data_blob(NULL, 0); uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; if (!cli->auth.a_u.ntlmssp_state) { 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_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n")); data_blob_free(&auth_blob); return NT_STATUS_NO_MEMORY; } switch (cli->auth.auth_level) { case PIPE_AUTH_LEVEL_PRIVACY: /* Data portion is encrypted. */ status = ntlmssp_seal_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,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?