#include "includes.h"
#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"
-#include "librpc/rpc/dcerpc_gssapi.h"
-#include "librpc/rpc/dcerpc_spnego.h"
+#include "librpc/crypto/gse.h"
+#include "auth/gensec/gensec.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_PARSE
return NT_STATUS_OK;
}
-/**
-* @brief Decodes a ncacn_packet
-*
-* @param mem_ctx The memory context on which to allocate the packet
-* elements
-* @param blob The blob of data to decode
-* @param r An empty ncacn_packet, must not be NULL
-*
-* @return a NTSTATUS error code
-*/
-NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
- const DATA_BLOB *blob,
- struct ncacn_packet *r,
- bool bigendian)
-{
- enum ndr_err_code ndr_err;
- struct ndr_pull *ndr;
-
- ndr = ndr_pull_init_blob(blob, mem_ctx);
- if (!ndr) {
- return NT_STATUS_NO_MEMORY;
- }
- if (bigendian) {
- ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
-
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- talloc_free(ndr);
- return ndr_map_error2ntstatus(ndr_err);
- }
- talloc_free(ndr);
-
- if (DEBUGLEVEL >= 10) {
- NDR_PRINT_DEBUG(ncacn_packet, r);
- }
-
- return NT_STATUS_OK;
-}
-
-/**
-* @brief NDR Encodes a NL_AUTH_MESSAGE
-*
-* @param mem_ctx The memory context the blob will be allocated on
-* @param r The NL_AUTH_MESSAGE to encode
-* @param blob [out] The encoded blob if successful
-*
-* @return a NTSTATUS error code
-*/
-NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx,
- struct NL_AUTH_MESSAGE *r,
- DATA_BLOB *blob)
-{
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_push_struct_blob(blob, mem_ctx, r,
- (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return ndr_map_error2ntstatus(ndr_err);
- }
-
- if (DEBUGLEVEL >= 10) {
- NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r);
- }
-
- return NT_STATUS_OK;
-}
-
/**
* @brief NDR Encodes a dcerpc_auth structure
*
return NT_STATUS_OK;
}
-/**
-* @brief Decodes a dcerpc_auth blob
-*
-* @param mem_ctx The memory context on which to allocate the packet
-* elements
-* @param blob The blob of data to decode
-* @param r An empty dcerpc_auth structure, must not be NULL
-*
-* @return a NTSTATUS error code
-*/
-NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
- const DATA_BLOB *blob,
- struct dcerpc_auth *r,
- bool bigendian)
-{
- enum ndr_err_code ndr_err;
- struct ndr_pull *ndr;
-
- ndr = ndr_pull_init_blob(blob, mem_ctx);
- if (!ndr) {
- return NT_STATUS_NO_MEMORY;
- }
- if (bigendian) {
- ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
-
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- talloc_free(ndr);
- return ndr_map_error2ntstatus(ndr_err);
- }
- talloc_free(ndr);
-
- if (DEBUGLEVEL >= 10) {
- NDR_PRINT_DEBUG(dcerpc_auth, r);
- }
-
- return NT_STATUS_OK;
-}
-
/**
* @brief Calculate how much data we can in a packet, including calculating
* auth token and pad lengths.
* @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
*/
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 max_xmit_frag,
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 gse_context *gse_ctx;
- enum dcerpc_AuthType auth_type;
- void *auth_ctx;
- bool seal = false;
- NTSTATUS status;
+ struct gensec_security *gensec_security;
/* no auth token cases first */
switch (auth->auth_level) {
return NT_STATUS_OK;
case DCERPC_AUTH_LEVEL_PRIVACY:
- seal = true;
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
/* Treat the same for all authenticated rpc requests. */
switch (auth->auth_type) {
case DCERPC_AUTH_TYPE_SPNEGO:
- /* compat for server code */
- if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
- *auth_len = NTLMSSP_SIG_SIZE;
- break;
- }
-
- 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);
+ case DCERPC_AUTH_TYPE_SCHANNEL:
+ gensec_security = auth->auth_ctx;
+ mod_len = (max_len % DCERPC_AUTH_PAD_ALIGNMENT);
+ *auth_len = gensec_sig_size(gensec_security, max_len - mod_len);
+ if (*auth_len == 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
break;
-
default:
return NT_STATUS_INVALID_PARAMETER;
}
max_len -= *auth_len;
+ mod_len = (max_len % DCERPC_AUTH_PAD_ALIGNMENT);
+ max_len -= mod_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;
- }
+ *pad_len = DCERPC_AUTH_PAD_LENGTH(*data_to_send);
*frag_len = header_len + *data_to_send + *pad_len
+ DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
Create and add the NTLMSSP sign/seal auth data.
********************************************************************/
-static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
+static NTSTATUS add_generic_auth_footer(struct gensec_security *gensec_security,
enum dcerpc_AuthLevel auth_level,
DATA_BLOB *rpc_out)
{
DATA_BLOB auth_blob;
NTSTATUS status;
- if (!auth_state) {
+ if (!gensec_security) {
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);
+ status = gensec_seal_packet(gensec_security,
+ 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;
}
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);
+ status = gensec_sign_packet(gensec_security,
+ 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;
}
Check/unseal the NTLMSSP auth data. (Unseal in place).
********************************************************************/
-static NTSTATUS get_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
+static NTSTATUS get_generic_auth_footer(struct gensec_security *gensec_security,
enum dcerpc_AuthLevel auth_level,
DATA_BLOB *data, DATA_BLOB *full_pkt,
DATA_BLOB *auth_token)
{
- switch (auth_level) {
- case DCERPC_AUTH_LEVEL_PRIVACY:
- /* Data portion is encrypted. */
- return auth_ntlmssp_unseal_packet(auth_state,
- data->data,
- data->length,
- full_pkt->data,
- full_pkt->length,
- auth_token);
-
- case DCERPC_AUTH_LEVEL_INTEGRITY:
- /* Data is signed. */
- return auth_ntlmssp_check_packet(auth_state,
- data->data,
- data->length,
- full_pkt->data,
- full_pkt->length,
- auth_token);
-
- default:
- return NT_STATUS_INVALID_PARAMETER;
- }
-}
-
-/*******************************************************************
- 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;
-}
-
-/*******************************************************************
- Check/unseal the Schannel auth data. (Unseal in place).
- ********************************************************************/
-
-static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx,
- struct schannel_state *auth_state,
- enum dcerpc_AuthLevel auth_level,
- DATA_BLOB *data, DATA_BLOB *full_pkt,
- DATA_BLOB *auth_token)
-{
- switch (auth_level) {
- case DCERPC_AUTH_LEVEL_PRIVACY:
- /* Data portion is encrypted. */
- return netsec_incoming_packet(auth_state,
- mem_ctx, true,
- data->data,
- data->length,
- auth_token);
-
- case DCERPC_AUTH_LEVEL_INTEGRITY:
- /* Data is signed. */
- return netsec_incoming_packet(auth_state,
- mem_ctx, false,
- data->data,
- data->length,
- auth_token);
-
- default:
- return NT_STATUS_INVALID_PARAMETER;
- }
-}
-
-/*******************************************************************
- Create and add the gssapi sign/seal auth data.
- ********************************************************************/
-
-static NTSTATUS add_gssapi_auth_footer(struct gse_context *gse_ctx,
- enum dcerpc_AuthLevel auth_level,
- DATA_BLOB *rpc_out)
-{
- DATA_BLOB data;
- DATA_BLOB auth_blob;
- NTSTATUS status;
-
- if (!gse_ctx) {
+ if (gensec_security == NULL) {
return NT_STATUS_INVALID_PARAMETER;
}
- data.data = rpc_out->data + DCERPC_RESPONSE_LENGTH;
- data.length = rpc_out->length - DCERPC_RESPONSE_LENGTH
- - DCERPC_AUTH_TRAILER_LENGTH;
-
- switch (auth_level) {
- case DCERPC_AUTH_LEVEL_PRIVACY:
- status = gse_seal(talloc_tos(), gse_ctx, &data, &auth_blob);
- break;
- case DCERPC_AUTH_LEVEL_INTEGRITY:
- status = gse_sign(talloc_tos(), gse_ctx, &data, &auth_blob);
- break;
- default:
- status = NT_STATUS_INTERNAL_ERROR;
- break;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to process packet: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- /* 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;
-}
-
-/*******************************************************************
- Check/unseal the gssapi auth data. (Unseal in place).
- ********************************************************************/
-
-static NTSTATUS get_gssapi_auth_footer(TALLOC_CTX *mem_ctx,
- struct gse_context *gse_ctx,
- enum dcerpc_AuthLevel auth_level,
- DATA_BLOB *data, DATA_BLOB *full_pkt,
- DATA_BLOB *auth_token)
-{
- /* TODO: pass in full_pkt when
- * DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN is set */
switch (auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
/* Data portion is encrypted. */
- return gse_unseal(mem_ctx, gse_ctx,
- data, auth_token);
+ return gensec_unseal_packet(gensec_security,
+ data->data,
+ data->length,
+ full_pkt->data,
+ full_pkt->length,
+ auth_token);
case DCERPC_AUTH_LEVEL_INTEGRITY:
/* Data is signed. */
- return gse_sigcheck(mem_ctx, gse_ctx,
- data, auth_token);
- default:
- return NT_STATUS_INVALID_PARAMETER;
- }
-}
-
-/*******************************************************************
- Create and add the spnego-negotiated sign/seal auth data.
- ********************************************************************/
-
-static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx,
- enum dcerpc_AuthLevel auth_level,
- DATA_BLOB *rpc_out)
-{
- enum dcerpc_AuthType auth_type;
- struct gse_context *gse_ctx;
- struct auth_ntlmssp_state *ntlmssp_ctx;
- void *auth_ctx;
- NTSTATUS status;
-
- if (!spnego_ctx) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- status = spnego_get_negotiated_mech(spnego_ctx,
- &auth_type, &auth_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- switch (auth_type) {
- case DCERPC_AUTH_TYPE_KRB5:
- gse_ctx = talloc_get_type(auth_ctx, struct gse_context);
- if (!gse_ctx) {
- status = NT_STATUS_INTERNAL_ERROR;
- break;
- }
- status = add_gssapi_auth_footer(gse_ctx,
- auth_level, rpc_out);
- break;
-
- case DCERPC_AUTH_TYPE_NTLMSSP:
- ntlmssp_ctx = talloc_get_type(auth_ctx,
- struct auth_ntlmssp_state);
- if (!ntlmssp_ctx) {
- status = NT_STATUS_INTERNAL_ERROR;
- break;
- }
- status = add_ntlmssp_auth_footer(ntlmssp_ctx,
- auth_level, rpc_out);
- break;
-
- default:
- status = NT_STATUS_INTERNAL_ERROR;
- break;
- }
-
- return status;
-}
-
-static NTSTATUS get_spnego_auth_footer(TALLOC_CTX *mem_ctx,
- struct spnego_context *sp_ctx,
- enum dcerpc_AuthLevel auth_level,
- DATA_BLOB *data, DATA_BLOB *full_pkt,
- DATA_BLOB *auth_token)
-{
- enum dcerpc_AuthType auth_type;
- struct auth_ntlmssp_state *ntlmssp_ctx;
- struct gse_context *gse_ctx;
- void *auth_ctx;
- NTSTATUS status;
-
- status = spnego_get_negotiated_mech(sp_ctx, &auth_type, &auth_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- switch (auth_type) {
- case DCERPC_AUTH_TYPE_KRB5:
- gse_ctx = talloc_get_type(auth_ctx,
- struct gse_context);
- if (!gse_ctx) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG(10, ("KRB5 auth\n"));
-
- return get_gssapi_auth_footer(mem_ctx, gse_ctx,
- auth_level,
- data, full_pkt,
- auth_token);
- case DCERPC_AUTH_TYPE_NTLMSSP:
- ntlmssp_ctx = talloc_get_type(auth_ctx,
- struct auth_ntlmssp_state);
- if (!ntlmssp_ctx) {
- return NT_STATUS_INVALID_PARAMETER;
- }
+ return gensec_check_packet(gensec_security,
+ data->data,
+ data->length,
+ full_pkt->data,
+ full_pkt->length,
+ auth_token);
- DEBUG(10, ("NTLMSSP auth\n"));
-
- return get_ntlmssp_auth_footer(ntlmssp_ctx,
- auth_level,
- data, full_pkt,
- auth_token);
default:
return NT_STATUS_INVALID_PARAMETER;
}
NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
size_t pad_len, DATA_BLOB *rpc_out)
{
- char pad[CLIENT_NDR_PADDING_SIZE] = { 0, };
+ struct gensec_security *gensec_security;
+ const char pad[DCERPC_AUTH_PAD_ALIGNMENT] = { 0, };
DATA_BLOB auth_info;
DATA_BLOB auth_blob;
NTSTATUS status;
}
if (pad_len) {
+ SMB_ASSERT(pad_len <= ARRAY_SIZE(pad));
+
/* Copy the sign/seal padding data. */
if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
return NT_STATUS_NO_MEMORY;
auth->auth_type,
auth->auth_level,
pad_len,
- 1 /* context id. */,
+ auth->auth_context_id,
&auth_blob,
&auth_info);
if (!NT_STATUS_IS_OK(status)) {
case DCERPC_AUTH_TYPE_NONE:
status = NT_STATUS_OK;
break;
- case DCERPC_AUTH_TYPE_SPNEGO:
- if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
- /* compat for server code */
- return add_ntlmssp_auth_footer(
- auth->a_u.auth_ntlmssp_state,
- auth->auth_level,
- rpc_out);
- }
- status = add_spnego_auth_footer(auth->a_u.spnego_state,
- auth->auth_level, rpc_out);
- break;
- case DCERPC_AUTH_TYPE_NTLMSSP:
- status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state,
+ default:
+ gensec_security = auth->auth_ctx;
+ status = add_generic_auth_footer(gensec_security,
auth->auth_level,
rpc_out);
break;
- case DCERPC_AUTH_TYPE_SCHANNEL:
- status = add_schannel_auth_footer(auth->a_u.schannel_auth,
- auth->auth_level,
- rpc_out);
- break;
- case DCERPC_AUTH_TYPE_KRB5:
- status = add_gssapi_auth_footer(auth->a_u.gssapi_state,
- auth->auth_level,
- rpc_out);
- break;
- default:
- status = NT_STATUS_INVALID_PARAMETER;
- break;
}
return status;
*
* @param auth The auth data for the connection
* @param pkt The actual ncacn_packet
-* @param pkt_trailer The stub_and_verifier part of the packet
+* @param pkt_trailer [in][out] The stub_and_verifier part of the packet,
+* the auth_trailer and padding will be removed.
* @param header_size The header size
* @param raw_pkt The whole raw packet data blob
-* @param pad_len [out] The padding length used in the packet
*
* @return A NTSTATUS error code
*/
NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
struct ncacn_packet *pkt,
DATA_BLOB *pkt_trailer,
- size_t header_size,
- DATA_BLOB *raw_pkt,
- size_t *pad_len)
+ uint8_t header_size,
+ DATA_BLOB *raw_pkt)
{
+ struct gensec_security *gensec_security;
NTSTATUS status;
struct dcerpc_auth auth_info;
uint32_t auth_length;
DATA_BLOB full_pkt;
DATA_BLOB data;
+ /*
+ * These check should be done in the caller.
+ */
+ SMB_ASSERT(raw_pkt->length == pkt->frag_length);
+ SMB_ASSERT(header_size <= pkt->frag_length);
+ SMB_ASSERT(pkt_trailer->length < pkt->frag_length);
+ SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length);
+
switch (auth->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
DEBUG(10, ("Requested Privacy.\n"));
if (pkt->auth_length != 0) {
break;
}
- *pad_len = 0;
return NT_STATUS_OK;
case DCERPC_AUTH_LEVEL_NONE:
"authenticated connection!\n"));
return NT_STATUS_INVALID_PARAMETER;
}
- *pad_len = 0;
return NT_STATUS_OK;
default:
return NT_STATUS_INVALID_PARAMETER;
}
- /* Paranioa checks for auth_length. */
- if (pkt->auth_length > pkt->frag_length) {
- return NT_STATUS_INFO_LENGTH_MISMATCH;
- }
- if (((unsigned int)pkt->auth_length
- + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
- ((unsigned int)pkt->auth_length
- + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
- /* Integer wrap attempt. */
- return NT_STATUS_INFO_LENGTH_MISMATCH;
+ if (pkt->auth_length == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
}
status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
return status;
}
+ if (auth_info.auth_type != auth->auth_type) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (auth_info.auth_level != auth->auth_level) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (auth_info.auth_context_id != auth->auth_context_id) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ pkt_trailer->length -= auth_length;
data = data_blob_const(raw_pkt->data + header_size,
- pkt_trailer->length - auth_length);
- full_pkt = data_blob_const(raw_pkt->data,
- raw_pkt->length - auth_info.credentials.length);
+ pkt_trailer->length);
+ full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length);
+ full_pkt.length -= auth_info.credentials.length;
switch (auth->auth_type) {
case DCERPC_AUTH_TYPE_NONE:
return NT_STATUS_OK;
- case DCERPC_AUTH_TYPE_SPNEGO:
- if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
- /* compat for server code */
- DEBUG(10, ("NTLMSSP auth\n"));
-
- status = get_ntlmssp_auth_footer(
- auth->a_u.auth_ntlmssp_state,
- auth->auth_level,
- &data, &full_pkt,
- &auth_info.credentials);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
- }
-
- status = get_spnego_auth_footer(pkt, auth->a_u.spnego_state,
- auth->auth_level,
- &data, &full_pkt,
- &auth_info.credentials);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
-
- case DCERPC_AUTH_TYPE_NTLMSSP:
-
- DEBUG(10, ("NTLMSSP auth\n"));
+ default:
+ DEBUG(10, ("GENSEC auth\n"));
- status = get_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state,
+ gensec_security = auth->auth_ctx;
+ status = get_generic_auth_footer(gensec_security,
auth->auth_level,
&data, &full_pkt,
&auth_info.credentials);
return status;
}
break;
-
- case DCERPC_AUTH_TYPE_SCHANNEL:
-
- DEBUG(10, ("SCHANNEL auth\n"));
-
- status = get_schannel_auth_footer(pkt,
- auth->a_u.schannel_auth,
- auth->auth_level,
- &data, &full_pkt,
- &auth_info.credentials);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
-
- case DCERPC_AUTH_TYPE_KRB5:
-
- DEBUG(10, ("KRB5 auth\n"));
-
- status = get_gssapi_auth_footer(pkt,
- auth->a_u.gssapi_state,
- auth->auth_level,
- &data, &full_pkt,
- &auth_info.credentials);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
-
- default:
- DEBUG(0, ("process_request_pdu: "
- "unknown auth type %u set.\n",
- (unsigned int)auth->auth_type));
- return NT_STATUS_INVALID_PARAMETER;
}
/* TODO: remove later
* pkt_trailer actually has a copy of the raw data, and they
* are still both used in later calls */
if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+ if (pkt_trailer->length != data.length) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
memcpy(pkt_trailer->data, data.data, data.length);
}
- *pad_len = auth_info.auth_pad_length;
+ pkt_trailer->length -= auth_info.auth_pad_length;
data_blob_free(&auth_info.credentials);
return NT_STATUS_OK;
}