static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) { struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; uint32_t sig_size; sig_size = netsec_outgoing_sig_size(state); return sig_size; }
/** * @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 header_len The length of the packet header * @param data_left The data left in the send buffer * @param max_xmit_frag The max fragment size. * @param pad_alignment The NDR padding size. * @param data_to_send [out] The max data we will send in the pdu * @param frag_len [out] The total length of the fragment * @param auth_len [out] The length of the auth trailer * @param pad_len [out] The padding to be applied * * @return A NT Error status code. */ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, size_t header_len, size_t data_left, size_t max_xmit_frag, size_t pad_alignment, size_t *data_to_send, size_t *frag_len, size_t *auth_len, size_t *pad_len) { size_t max_len; size_t mod_len; struct schannel_state *schannel_auth; struct spnego_context *spnego_ctx; struct gse_context *gse_ctx; enum spnego_mech 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: max_len = max_xmit_frag - header_len; *data_to_send = MIN(max_len, data_left); *pad_len = 0; *auth_len = 0; *frag_len = header_len + *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 - header_len - DCERPC_AUTH_TRAILER_LENGTH; /* Treat the same for all authenticated rpc requests. */ switch (auth->auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: spnego_ctx = talloc_get_type_abort(auth->auth_ctx, struct spnego_context); status = spnego_get_negotiated_mech(spnego_ctx, &auth_type, &auth_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } switch (auth_type) { case SPNEGO_NTLMSSP: *auth_len = NTLMSSP_SIG_SIZE; break; case SPNEGO_KRB5: gse_ctx = talloc_get_type_abort(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: schannel_auth = talloc_get_type_abort(auth->auth_ctx, struct schannel_state); *auth_len = netsec_outgoing_sig_size(schannel_auth); break; case DCERPC_AUTH_TYPE_KRB5: gse_ctx = talloc_get_type_abort(auth->auth_ctx, struct gse_context); *auth_len = gse_get_signature_length(gse_ctx, seal, max_len); break; default: return NT_STATUS_INVALID_PARAMETER; } max_len -= *auth_len; *data_to_send = MIN(max_len, data_left); mod_len = (header_len + *data_to_send) % pad_alignment; if (mod_len) { *pad_len = pad_alignment - mod_len; } else { *pad_len = 0; } if (*data_to_send + *pad_len > max_len) { *data_to_send -= pad_alignment; } *frag_len = header_len + *data_to_send + *pad_len + DCERPC_AUTH_TRAILER_LENGTH + *auth_len; 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 header_len The length of the packet header * @param data_left The data left in the send buffer * @param max_xmit_frag The max fragment size. * @param pad_alignment The NDR padding size. * @param data_to_send [out] The max data we will send in the pdu * @param frag_len [out] The total length of the fragment * @param auth_len [out] The length of the auth trailer * @param pad_len [out] The padding to be applied * * @return A NT Error status code. */ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, size_t header_len, size_t data_left, size_t max_xmit_frag, size_t pad_alignment, size_t *data_to_send, size_t *frag_len, size_t *auth_len, size_t *pad_len) { size_t max_len; size_t mod_len; struct gensec_security *gensec_security; struct schannel_state *schannel_auth; /* no auth token cases first */ switch (auth->auth_level) { case DCERPC_AUTH_LEVEL_NONE: case DCERPC_AUTH_LEVEL_CONNECT: case DCERPC_AUTH_LEVEL_PACKET: max_len = max_xmit_frag - header_len; *data_to_send = MIN(max_len, data_left); *pad_len = 0; *auth_len = 0; *frag_len = header_len + *data_to_send; return NT_STATUS_OK; case DCERPC_AUTH_LEVEL_PRIVACY: 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 - header_len - DCERPC_AUTH_TRAILER_LENGTH; /* Treat the same for all authenticated rpc requests. */ switch (auth->auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(auth->auth_ctx, struct gensec_security); *auth_len = gensec_sig_size(gensec_security, max_len); break; case DCERPC_AUTH_TYPE_SCHANNEL: schannel_auth = talloc_get_type_abort(auth->auth_ctx, struct schannel_state); *auth_len = netsec_outgoing_sig_size(schannel_auth); break; default: return NT_STATUS_INVALID_PARAMETER; } max_len -= *auth_len; *data_to_send = MIN(max_len, data_left); mod_len = (header_len + *data_to_send) % pad_alignment; if (mod_len) { *pad_len = pad_alignment - mod_len; } else { *pad_len = 0; } if (*data_to_send + *pad_len > max_len) { *data_to_send -= pad_alignment; } *frag_len = header_len + *data_to_send + *pad_len + DCERPC_AUTH_TRAILER_LENGTH + *auth_len; return NT_STATUS_OK; }