librpc/rpc: move dcerpc_pull_ncacn_packet() from source3/librpc/rpc/ to the toplevel
[kamenim/samba-autobuild/.git] / source3 / librpc / rpc / dcerpc_helpers.c
index f8ca8e62762cfb02de4e1147420e782c26c75264..88d27d0fafdc81618edb233a2d8c75c48b796ae3 100644 (file)
 #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
@@ -86,75 +81,6 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
        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
 *
@@ -200,47 +126,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
        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.
@@ -249,7 +134,6 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
 * @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
@@ -259,17 +143,13 @@ NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
 */
 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) {
@@ -284,7 +164,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
                return NT_STATUS_OK;
 
        case DCERPC_AUTH_LEVEL_PRIVACY:
-               seal = true;
                break;
 
        case DCERPC_AUTH_LEVEL_INTEGRITY:
@@ -302,68 +181,27 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
        /* 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;
@@ -375,7 +213,7 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
  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)
 {
@@ -385,21 +223,21 @@ static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
        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;
                }
@@ -407,14 +245,14 @@ static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
 
        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;
                }
@@ -443,305 +281,34 @@ static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
  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;
        }
@@ -759,7 +326,8 @@ static NTSTATUS get_spnego_auth_footer(TALLOC_CTX *mem_ctx,
 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;
@@ -769,6 +337,8 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
        }
 
        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;
@@ -783,7 +353,7 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
                                         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)) {
@@ -804,35 +374,12 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
        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;
@@ -843,26 +390,34 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
 *
 * @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"));
@@ -876,7 +431,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                if (pkt->auth_length != 0) {
                        break;
                }
-               *pad_len = 0;
                return NT_STATUS_OK;
 
        case DCERPC_AUTH_LEVEL_NONE:
@@ -885,7 +439,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                                  "authenticated connection!\n"));
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               *pad_len = 0;
                return NT_STATUS_OK;
 
        default:
@@ -894,16 +447,8 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                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,
@@ -912,45 +457,33 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                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);
@@ -958,40 +491,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                        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
@@ -999,10 +498,13 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
         * 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;
 }