From 31393334194be7763072900408bb61ebb7c1d11a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 19 Jul 2010 16:10:35 -0400 Subject: s3-dcerpc: Move dcerpc_add_auth_footer() to the common helpers file --- source3/librpc/rpc/dcerpc.h | 2 + source3/librpc/rpc/dcerpc_helpers.c | 216 ++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) (limited to 'source3/librpc') diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index bb7bd34de8..319acce990 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -139,5 +139,7 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct dcerpc_auth *r, bool bigendian); +NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, + size_t pad_len, DATA_BLOB *rpc_out); #endif /* __DCERPC_H__ */ diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 5c92a792e9..0e43e7ad56 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -22,6 +22,10 @@ #include "librpc/rpc/dcerpc.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_schannel.h" +#include "../libcli/auth/schannel.h" +#include "../libcli/auth/spnego.h" +#include "../libcli/auth/ntlmssp.h" +#include "ntlmssp_wrap.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE @@ -234,3 +238,215 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } + +/******************************************************************* + Create and add the NTLMSSP sign/seal auth data. + ********************************************************************/ + +static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state, + enum dcerpc_AuthLevel auth_level, + DATA_BLOB *rpc_out) +{ + uint16_t data_and_pad_len = rpc_out->length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH; + DATA_BLOB auth_blob; + NTSTATUS status; + + if (!auth_state) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + /* Data portion is encrypted. */ + status = auth_ntlmssp_seal_packet(auth_state, + rpc_out->data, + rpc_out->data + + DCERPC_RESPONSE_LENGTH, + data_and_pad_len, + rpc_out->data, + rpc_out->length, + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = auth_ntlmssp_sign_packet(auth_state, + rpc_out->data, + rpc_out->data + + DCERPC_RESPONSE_LENGTH, + data_and_pad_len, + rpc_out->data, + rpc_out->length, + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + break; + + default: + /* Can't happen. */ + smb_panic("bad auth level"); + /* Notreached. */ + return NT_STATUS_INVALID_PARAMETER; + } + + /* Finally attach the blob. */ + if (!data_blob_append(NULL, rpc_out, + auth_blob.data, auth_blob.length)) { + DEBUG(0, ("Failed to add %u bytes auth blob.\n", + (unsigned int)auth_blob.length)); + return NT_STATUS_NO_MEMORY; + } + data_blob_free(&auth_blob); + + return NT_STATUS_OK; +} + +/******************************************************************* + Create and add the schannel sign/seal auth data. + ********************************************************************/ + +static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, + enum dcerpc_AuthLevel auth_level, + DATA_BLOB *rpc_out) +{ + uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH; + size_t data_and_pad_len = rpc_out->length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH; + DATA_BLOB auth_blob; + NTSTATUS status; + + if (!sas) { + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", + sas->seq_num)); + + switch (auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = netsec_outgoing_packet(sas, + rpc_out->data, + true, + data_p, + data_and_pad_len, + &auth_blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = netsec_outgoing_packet(sas, + rpc_out->data, + false, + data_p, + data_and_pad_len, + &auth_blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n", + nt_errstr(status))); + return status; + } + + if (DEBUGLEVEL >= 10) { + dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); + } + + /* Finally attach the blob. */ + if (!data_blob_append(NULL, rpc_out, + auth_blob.data, auth_blob.length)) { + return NT_STATUS_NO_MEMORY; + } + data_blob_free(&auth_blob); + + return NT_STATUS_OK; +} + +/** +* @brief Append an auth footer according to what is the current mechanism +* +* @param auth The pipe_auth_data associated with the connection +* @param pad_len The padding used in the packet +* @param rpc_out Packet blob up to and including the auth header +* +* @return A NTSTATUS error code. +*/ +NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, + size_t pad_len, DATA_BLOB *rpc_out) +{ + enum dcerpc_AuthType auth_type; + char pad[CLIENT_NDR_PADDING_SIZE] = { 0, }; + DATA_BLOB auth_info; + DATA_BLOB auth_blob; + NTSTATUS status; + + if (auth->auth_type == PIPE_AUTH_TYPE_NONE) { + return NT_STATUS_OK; + } + + if (pad_len) { + /* Copy the sign/seal padding data. */ + if (!data_blob_append(NULL, rpc_out, pad, pad_len)) { + return NT_STATUS_NO_MEMORY; + } + } + + auth_type = map_pipe_auth_type_to_rpc_auth_type(auth->auth_type); + + /* marshall the dcerpc_auth with an actually empty auth_blob. + * This is needed because the ntmlssp signature includes the + * auth header. We will append the actual blob later. */ + auth_blob = data_blob_null; + status = dcerpc_push_dcerpc_auth(rpc_out->data, + auth_type, + auth->auth_level, + pad_len, + 1 /* context id. */, + &auth_blob, + &auth_info); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* append the header */ + if (!data_blob_append(NULL, rpc_out, + auth_info.data, auth_info.length)) { + DEBUG(0, ("Failed to add %u bytes auth blob.\n", + (unsigned int)auth_info.length)); + return NT_STATUS_NO_MEMORY; + } + data_blob_free(&auth_info); + + /* Generate any auth sign/seal and add the auth footer. */ + switch (auth->auth_type) { + case PIPE_AUTH_TYPE_NONE: + status = NT_STATUS_OK; + break; + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state, + auth->auth_level, + rpc_out); + break; + case PIPE_AUTH_TYPE_SCHANNEL: + status = add_schannel_auth_footer(auth->a_u.schannel_auth, + auth->auth_level, + rpc_out); + break; + default: + status = NT_STATUS_INVALID_PARAMETER; + break; + } + + return status; +} + -- cgit