diff options
author | Simo Sorce <idra@samba.org> | 2010-07-30 11:27:40 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2010-07-30 14:55:27 -0400 |
commit | a9d3a596a7c4d7e5775751cbce74e2fb07ce2192 (patch) | |
tree | aa794c042c5b6831ee743bd1ef6a09e5757a5b76 /source3/librpc/rpc | |
parent | 9329a9fe848761e2835ff58123d8f64d8bab35b2 (diff) | |
download | samba-a9d3a596a7c4d7e5775751cbce74e2fb07ce2192.tar.gz samba-a9d3a596a7c4d7e5775751cbce74e2fb07ce2192.tar.bz2 samba-a9d3a596a7c4d7e5775751cbce74e2fb07ce2192.zip |
s3-dcerpc: Make function to guess pdu sizes common.
Diffstat (limited to 'source3/librpc/rpc')
-rw-r--r-- | source3/librpc/rpc/dcerpc.h | 4 | ||||
-rw-r--r-- | source3/librpc/rpc/dcerpc_helpers.c | 117 |
2 files changed, 121 insertions, 0 deletions
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. ********************************************************************/ |