From a9d3a596a7c4d7e5775751cbce74e2fb07ce2192 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 30 Jul 2010 11:27:40 -0400 Subject: s3-dcerpc: Make function to guess pdu sizes common. --- source3/librpc/rpc/dcerpc.h | 4 ++ source3/librpc/rpc/dcerpc_helpers.c | 117 ++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_pipe.c | 121 +++--------------------------------- 3 files changed, 130 insertions(+), 112 deletions(-) (limited to 'source3') diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index d170daad9f..fd80dbeb04 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -139,6 +139,10 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct dcerpc_auth *r, bool bigendian); +NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, + size_t data_left, size_t max_xmit_frag, + size_t *data_to_send, size_t *frag_len, + size_t *auth_len, size_t *pad_len); NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, size_t pad_len, DATA_BLOB *rpc_out); NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 26b44de5ea..161154fe3b 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -241,6 +241,123 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/** +* @brief Calculate how much data we can in a packet, including calculating +* auth token and pad lengths. +* +* @param auth The pipe_auth_data structure for this pipe. +* @param data_left The data left in the send buffer +* @param data_to_send The max data we will send in the pdu +* @param frag_len The total length of the fragment +* @param auth_len The length of the auth trailer +* @param pad_len The padding to be applied +* +* @return A NT Error status code. +*/ +NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, + size_t data_left, size_t max_xmit_frag, + size_t *data_to_send, size_t *frag_len, + size_t *auth_len, size_t *pad_len) +{ + size_t data_space; + size_t max_len; + size_t mod_len; + struct gse_context *gse_ctx; + enum dcerpc_AuthType auth_type; + void *auth_ctx; + bool seal = false; + NTSTATUS status; + + /* no auth token cases first */ + switch (auth->auth_level) { + case DCERPC_AUTH_LEVEL_NONE: + case DCERPC_AUTH_LEVEL_CONNECT: + case DCERPC_AUTH_LEVEL_PACKET: + data_space = max_xmit_frag - DCERPC_REQUEST_LENGTH; + *data_to_send = MIN(data_space, data_left); + *pad_len = 0; + *auth_len = 0; + *frag_len = DCERPC_REQUEST_LENGTH + *data_to_send; + return NT_STATUS_OK; + + case DCERPC_AUTH_LEVEL_PRIVACY: + seal = true; + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + + /* Sign/seal case, calculate auth and pad lengths */ + + max_len = max_xmit_frag + - DCERPC_REQUEST_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH; + + /* Treat the same for all authenticated rpc requests. */ + switch (auth->auth_type) { + case DCERPC_AUTH_TYPE_SPNEGO: + status = spnego_get_negotiated_mech(auth->a_u.spnego_state, + &auth_type, &auth_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + switch (auth_type) { + case DCERPC_AUTH_TYPE_NTLMSSP: + *auth_len = NTLMSSP_SIG_SIZE; + break; + + case DCERPC_AUTH_TYPE_KRB5: + gse_ctx = talloc_get_type(auth_ctx, + struct gse_context); + if (!gse_ctx) { + return NT_STATUS_INVALID_PARAMETER; + } + *auth_len = gse_get_signature_length(gse_ctx, + seal, max_len); + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + break; + + case DCERPC_AUTH_TYPE_NTLMSSP: + *auth_len = NTLMSSP_SIG_SIZE; + break; + + case DCERPC_AUTH_TYPE_SCHANNEL: + *auth_len = NL_AUTH_SIGNATURE_SIZE; + break; + + case DCERPC_AUTH_TYPE_KRB5: + *auth_len = gse_get_signature_length(auth->a_u.gssapi_state, + seal, max_len); + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + data_space = max_len - *auth_len; + + *data_to_send = MIN(data_space, data_left); + mod_len = *data_to_send % CLIENT_NDR_PADDING_SIZE; + if (mod_len) { + *pad_len = CLIENT_NDR_PADDING_SIZE - mod_len; + } else { + *pad_len = 0; + } + *frag_len = DCERPC_REQUEST_LENGTH + *data_to_send + *pad_len + + DCERPC_AUTH_TRAILER_LENGTH + *auth_len; + + return NT_STATUS_OK; +} + /******************************************************************* Create and add the NTLMSSP sign/seal auth data. ********************************************************************/ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 02e4ec6ae2..99e856dfd8 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1184,109 +1184,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, return ret; } -/******************************************************************* - Calculate how much data we're going to send in this packet, also - work out any sign/seal padding length. - ********************************************************************/ - -static NTSTATUS calculate_data_len_tosend(struct rpc_pipe_client *cli, - uint32_t data_left, - uint32_t *data_to_send, - uint16_t *p_frag_len, - uint16_t *p_auth_len, - uint32_t *p_ss_padding) -{ - uint32_t data_space, data_len; - size_t max_len; - struct gse_context *gse_ctx; - enum dcerpc_AuthType auth_type; - void *auth_ctx; - NTSTATUS status; - - switch (cli->auth->auth_level) { - case DCERPC_AUTH_LEVEL_NONE: - case DCERPC_AUTH_LEVEL_CONNECT: - case DCERPC_AUTH_LEVEL_PACKET: - data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH; - data_len = MIN(data_space, data_left); - *p_ss_padding = 0; - *p_auth_len = 0; - *p_frag_len = DCERPC_REQUEST_LENGTH + data_len; - *data_to_send = data_len; - return NT_STATUS_OK; - - case DCERPC_AUTH_LEVEL_INTEGRITY: - case DCERPC_AUTH_LEVEL_PRIVACY: - max_len = cli->max_xmit_frag - - DCERPC_REQUEST_LENGTH - - DCERPC_AUTH_TRAILER_LENGTH; - - /* Treat the same for all authenticated rpc requests. */ - switch(cli->auth->auth_type) { - case DCERPC_AUTH_TYPE_SPNEGO: - status = spnego_get_negotiated_mech( - cli->auth->a_u.spnego_state, - &auth_type, &auth_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - switch (auth_type) { - case DCERPC_AUTH_TYPE_NTLMSSP: - *p_auth_len = NTLMSSP_SIG_SIZE; - break; - case DCERPC_AUTH_TYPE_KRB5: - gse_ctx = talloc_get_type(auth_ctx, - struct gse_context); - if (!gse_ctx) { - return NT_STATUS_INVALID_PARAMETER; - } - *p_auth_len = gse_get_signature_length(gse_ctx, - (cli->auth->auth_level == - DCERPC_AUTH_LEVEL_PRIVACY), - max_len); - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - break; - case DCERPC_AUTH_TYPE_NTLMSSP: - *p_auth_len = NTLMSSP_SIG_SIZE; - break; - case DCERPC_AUTH_TYPE_SCHANNEL: - *p_auth_len = NL_AUTH_SIGNATURE_SIZE; - break; - case DCERPC_AUTH_TYPE_KRB5: - *p_auth_len = gse_get_signature_length( - cli->auth->a_u.gssapi_state, - (cli->auth->auth_level == - DCERPC_AUTH_LEVEL_PRIVACY), - max_len); - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - - data_space = max_len - *p_auth_len; - - data_len = MIN(data_space, data_left); - *p_ss_padding = 0; - if (data_len % CLIENT_NDR_PADDING_SIZE) { - *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE); - } - *p_frag_len = DCERPC_REQUEST_LENGTH - + data_len + *p_ss_padding - + DCERPC_AUTH_TRAILER_LENGTH - + *p_auth_len; - *data_to_send = data_len; - return NT_STATUS_OK; - - default: - break; - } - - return NT_STATUS_INVALID_PARAMETER; -} - /******************************************************************* External interface. Does an rpc request on a pipe. Incoming data is NDR encoded in in_data. @@ -1378,21 +1275,21 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, bool *is_last_frag) { - uint32_t data_sent_thistime; - uint16_t auth_len; - uint16_t frag_len; + size_t data_sent_thistime; + size_t auth_len; + size_t frag_len; uint8_t flags = 0; - uint32_t pad_len; - uint32_t data_left; + size_t pad_len; + size_t data_left; NTSTATUS status; union dcerpc_payload u; data_left = state->req_data->length - state->req_data_sent; - status = calculate_data_len_tosend(state->cli, data_left, - &data_sent_thistime, - &frag_len, &auth_len, - &pad_len); + status = dcerpc_guess_sizes(state->cli->auth, data_left, + state->cli->max_xmit_frag, + &data_sent_thistime, + &frag_len, &auth_len, &pad_len); if (!NT_STATUS_IS_OK(status)) { return status; } -- cgit