diff options
-rw-r--r-- | source3/librpc/rpc/dcerpc.h | 2 | ||||
-rw-r--r-- | source3/librpc/rpc/dcerpc_helpers.c | 216 | ||||
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 203 |
3 files changed, 218 insertions, 203 deletions
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; +} + diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d04e56207e..759cfc5c22 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1581,209 +1581,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, } /******************************************************************* - Create and add the NTLMSSP sign/seal auth header and 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 header and 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; -} - -static 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; -} - -/******************************************************************* Calculate how much data we're going to send in this packet, also work out any sign/seal padding length. ********************************************************************/ |