s3: Fix some 64-bit warnings
[sfrench/samba-autobuild/.git] / source3 / rpc_client / cli_pipe.c
index a667a9fb13afb9c4a968c8beb8b03e0ee1edf391..9a1aba7b0d633230176900590dc9b8d4bdb92d73 100644 (file)
  */
 
 #include "includes.h"
-#include "../libcli/auth/libcli_auth.h"
 #include "librpc/gen_ndr/cli_epmapper.h"
 #include "../librpc/gen_ndr/ndr_schannel.h"
+#include "../librpc/gen_ndr/ndr_lsa.h"
+#include "../librpc/gen_ndr/ndr_dssetup.h"
+#include "../librpc/gen_ndr/ndr_samr.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "../librpc/gen_ndr/ndr_srvsvc.h"
+#include "../librpc/gen_ndr/ndr_wkssvc.h"
+#include "../librpc/gen_ndr/ndr_winreg.h"
+#include "../librpc/gen_ndr/ndr_spoolss.h"
+#include "../librpc/gen_ndr/ndr_dfs.h"
+#include "../librpc/gen_ndr/ndr_echo.h"
+#include "../librpc/gen_ndr/ndr_initshutdown.h"
+#include "../librpc/gen_ndr/ndr_svcctl.h"
+#include "../librpc/gen_ndr/ndr_eventlog.h"
+#include "../librpc/gen_ndr/ndr_ntsvcs.h"
+#include "../librpc/gen_ndr/ndr_epmapper.h"
+#include "../librpc/gen_ndr/ndr_drsuapi.h"
+#include "../libcli/auth/schannel.h"
+#include "../libcli/auth/spnego.h"
+#include "smb_krb5.h"
+#include "../libcli/auth/ntlmssp.h"
+#include "rpc_client/cli_netlogon.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "librpc/rpc/dcerpc.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_CLI
 
-/*******************************************************************
-interface/version dce/rpc pipe identification
-********************************************************************/
-
-#define PIPE_SRVSVC   "\\PIPE\\srvsvc"
-#define PIPE_SAMR     "\\PIPE\\samr"
-#define PIPE_WINREG   "\\PIPE\\winreg"
-#define PIPE_WKSSVC   "\\PIPE\\wkssvc"
-#define PIPE_NETLOGON "\\PIPE\\NETLOGON"
-#define PIPE_NTLSA    "\\PIPE\\ntlsa"
-#define PIPE_NTSVCS   "\\PIPE\\ntsvcs"
-#define PIPE_LSASS    "\\PIPE\\lsass"
-#define PIPE_LSARPC   "\\PIPE\\lsarpc"
-#define PIPE_SPOOLSS  "\\PIPE\\spoolss"
-#define PIPE_NETDFS   "\\PIPE\\netdfs"
-#define PIPE_ECHO     "\\PIPE\\rpcecho"
-#define PIPE_SHUTDOWN "\\PIPE\\initshutdown"
-#define PIPE_EPM      "\\PIPE\\epmapper"
-#define PIPE_SVCCTL   "\\PIPE\\svcctl"
-#define PIPE_EVENTLOG "\\PIPE\\eventlog"
-#define PIPE_EPMAPPER "\\PIPE\\epmapper"
-#define PIPE_DRSUAPI  "\\PIPE\\drsuapi"
-
-/*
- * IMPORTANT!!  If you update this structure, make sure to
- * update the index #defines in smb.h.
- */
+static const char *get_pipe_name_from_iface(
+       TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
+{
+       int i;
+       const struct ndr_interface_string_array *ep = interface->endpoints;
+       char *p;
 
-static const struct pipe_id_info {
-       /* the names appear not to matter: the syntaxes _do_ matter */
+       for (i=0; i<ep->count; i++) {
+               if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
+                       break;
+               }
+       }
+       if (i == ep->count) {
+               return NULL;
+       }
 
-       const char *client_pipe;
-       const struct ndr_syntax_id *abstr_syntax; /* this one is the abstract syntax id */
-} pipe_names [] =
+       /*
+        * extract the pipe name without \\pipe from for example
+        * ncacn_np:[\\pipe\\epmapper]
+        */
+       p = strchr(ep->names[i]+15, ']');
+       if (p == NULL) {
+               return "PIPE";
+       }
+       return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
+}
+
+static const struct ndr_interface_table **interfaces;
+
+bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
 {
-       { PIPE_LSARPC,          &ndr_table_lsarpc.syntax_id },
-       { PIPE_LSARPC,          &ndr_table_dssetup.syntax_id },
-       { PIPE_SAMR,            &ndr_table_samr.syntax_id },
-       { PIPE_NETLOGON,        &ndr_table_netlogon.syntax_id },
-       { PIPE_SRVSVC,          &ndr_table_srvsvc.syntax_id },
-       { PIPE_WKSSVC,          &ndr_table_wkssvc.syntax_id },
-       { PIPE_WINREG,          &ndr_table_winreg.syntax_id },
-       { PIPE_SPOOLSS,         &ndr_table_spoolss.syntax_id },
-       { PIPE_NETDFS,          &ndr_table_netdfs.syntax_id },
-       { PIPE_ECHO,            &ndr_table_rpcecho.syntax_id },
-       { PIPE_SHUTDOWN,        &ndr_table_initshutdown.syntax_id },
-       { PIPE_SVCCTL,          &ndr_table_svcctl.syntax_id },
-       { PIPE_EVENTLOG,        &ndr_table_eventlog.syntax_id },
-       { PIPE_NTSVCS,          &ndr_table_ntsvcs.syntax_id },
-       { PIPE_EPMAPPER,        &ndr_table_epmapper.syntax_id },
-       { PIPE_DRSUAPI,         &ndr_table_drsuapi.syntax_id },
-       { NULL, NULL }
-};
+       int num_interfaces = talloc_array_length(interfaces);
+       const struct ndr_interface_table **tmp;
+       int i;
+
+       for (i=0; i<num_interfaces; i++) {
+               if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
+                                       &interface->syntax_id)) {
+                       return true;
+               }
+       }
+
+       tmp = talloc_realloc(NULL, interfaces,
+                            const struct ndr_interface_table *,
+                            num_interfaces + 1);
+       if (tmp == NULL) {
+               DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
+               return false;
+       }
+       interfaces = tmp;
+       interfaces[num_interfaces] = interface;
+       return true;
+}
+
+static bool initialize_interfaces(void)
+{
+       if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_samr)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_winreg)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
+               return false;
+       }
+       if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
+               return false;
+       }
+       return true;
+}
+
+const struct ndr_interface_table *get_iface_from_syntax(
+       const struct ndr_syntax_id *syntax)
+{
+       int num_interfaces;
+       int i;
+
+       if (interfaces == NULL) {
+               if (!initialize_interfaces()) {
+                       return NULL;
+               }
+       }
+       num_interfaces = talloc_array_length(interfaces);
+
+       for (i=0; i<num_interfaces; i++) {
+               if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
+                       return interfaces[i];
+               }
+       }
+
+       return NULL;
+}
 
 /****************************************************************************
  Return the pipe name from the interface.
  ****************************************************************************/
 
-const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
+const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
+                                     const struct ndr_syntax_id *syntax)
 {
+       const struct ndr_interface_table *interface;
        char *guid_str;
        const char *result;
-       int i;
-       for (i = 0; pipe_names[i].client_pipe; i++) {
-               if (ndr_syntax_id_equal(pipe_names[i].abstr_syntax,
-                                       interface)) {
-                       return &pipe_names[i].client_pipe[5];
+
+       interface = get_iface_from_syntax(syntax);
+       if (interface != NULL) {
+               result = get_pipe_name_from_iface(mem_ctx, interface);
+               if (result != NULL) {
+                       return result;
                }
        }
 
@@ -100,12 +200,12 @@ const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
         * interested in the known pipes mentioned in pipe_names[]
         */
 
-       guid_str = GUID_string(talloc_tos(), &interface->uuid);
+       guid_str = GUID_string(talloc_tos(), &syntax->uuid);
        if (guid_str == NULL) {
                return NULL;
        }
-       result = talloc_asprintf(talloc_tos(), "Interface %s.%d", guid_str,
-                                (int)interface->if_version);
+       result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
+                                (int)syntax->if_version);
        TALLOC_FREE(guid_str);
 
        if (result == NULL) {
@@ -118,7 +218,7 @@ const char *get_pipe_name_from_iface(const struct ndr_syntax_id *interface)
  Map internal value to wire value.
  ********************************************************************/
 
-static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
+enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
 {
        switch (auth_type) {
 
@@ -170,32 +270,6 @@ static uint32 get_rpc_call_id(void)
        return ++call_id;
 }
 
-/*
- * Realloc pdu to have a least "size" bytes
- */
-
-static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
-{
-       size_t extra_size;
-
-       if (prs_data_size(pdu) >= size) {
-               return true;
-       }
-
-       extra_size = size - prs_data_size(pdu);
-
-       if (!prs_force_grow(pdu, extra_size)) {
-               DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
-                         "%d bytes.\n", (int)extra_size));
-               return false;
-       }
-
-       DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
-                 (int)extra_size, prs_data_size(pdu)));
-       return true;
-}
-
-
 /*******************************************************************
  Use SMBreadX to get rest of one fragment's worth of rpc data.
  Reads the whole size or give an error message
@@ -361,30 +435,6 @@ static NTSTATUS rpc_write_recv(struct tevent_req *req)
 }
 
 
-static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
-                                struct rpc_hdr_info *prhdr,
-                                prs_struct *pdu)
-{
-       /*
-        * This next call sets the endian bit correctly in current_pdu. We
-        * will propagate this to rbuf later.
-        */
-
-       if(!smb_io_rpc_hdr("rpc_hdr   ", prhdr, pdu, 0)) {
-               DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
-               return NT_STATUS_BUFFER_TOO_SMALL;
-       }
-
-       if (prhdr->frag_len > cli->max_recv_frag) {
-               DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
-                         " we only allow %d\n", (int)prhdr->frag_len,
-                         (int)cli->max_recv_frag));
-               return NT_STATUS_BUFFER_TOO_SMALL;
-       }
-
-       return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Try and get a PDU's worth of data from current_pdu. If not, then read more
  from the wire.
@@ -393,8 +443,8 @@ static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
 struct get_complete_frag_state {
        struct event_context *ev;
        struct rpc_pipe_client *cli;
-       struct rpc_hdr_info *prhdr;
-       prs_struct *pdu;
+       uint16_t frag_len;
+       DATA_BLOB *pdu;
 };
 
 static void get_complete_frag_got_header(struct tevent_req *subreq);
@@ -403,12 +453,11 @@ static void get_complete_frag_got_rest(struct tevent_req *subreq);
 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
                                                 struct event_context *ev,
                                                 struct rpc_pipe_client *cli,
-                                                struct rpc_hdr_info *prhdr,
-                                                prs_struct *pdu)
+                                                DATA_BLOB *pdu)
 {
        struct tevent_req *req, *subreq;
        struct get_complete_frag_state *state;
-       uint32_t pdu_len;
+       size_t received;
        NTSTATUS status;
 
        req = tevent_req_create(mem_ctx, &state,
@@ -418,20 +467,19 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
        }
        state->ev = ev;
        state->cli = cli;
-       state->prhdr = prhdr;
+       state->frag_len = RPC_HEADER_LEN;
        state->pdu = pdu;
 
-       pdu_len = prs_data_size(pdu);
-       if (pdu_len < RPC_HEADER_LEN) {
-               if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
+       received = pdu->length;
+       if (received < RPC_HEADER_LEN) {
+               if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
                        status = NT_STATUS_NO_MEMORY;
                        goto post_status;
                }
-               subreq = rpc_read_send(
-                       state, state->ev,
-                       state->cli->transport,
-                       (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
-                       RPC_HEADER_LEN - pdu_len);
+               subreq = rpc_read_send(state, state->ev,
+                                       state->cli->transport,
+                                       pdu->data + received,
+                                       RPC_HEADER_LEN - received);
                if (subreq == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto post_status;
@@ -441,23 +489,20 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
                return req;
        }
 
-       status = parse_rpc_header(cli, prhdr, pdu);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto post_status;
-       }
+       state->frag_len = dcerpc_get_frag_length(pdu);
 
        /*
         * Ensure we have frag_len bytes of data.
         */
-       if (pdu_len < prhdr->frag_len) {
-               if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
+       if (received < state->frag_len) {
+               if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
                        status = NT_STATUS_NO_MEMORY;
                        goto post_status;
                }
                subreq = rpc_read_send(state, state->ev,
-                                      state->cli->transport,
-                                      (uint8_t *)(prs_data_p(pdu) + pdu_len),
-                                      prhdr->frag_len - pdu_len);
+                                       state->cli->transport,
+                                       pdu->data + received,
+                                       state->frag_len - received);
                if (subreq == NULL) {
                        status = NT_STATUS_NO_MEMORY;
                        goto post_status;
@@ -492,13 +537,9 @@ static void get_complete_frag_got_header(struct tevent_req *subreq)
                return;
        }
 
-       status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
-       }
+       state->frag_len = dcerpc_get_frag_length(state->pdu);
 
-       if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
+       if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -508,10 +549,9 @@ static void get_complete_frag_got_header(struct tevent_req *subreq)
         * RPC_HEADER_LEN bytes into state->pdu.
         */
 
-       subreq = rpc_read_send(
-               state, state->ev, state->cli->transport,
-               (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
-               state->prhdr->frag_len - RPC_HEADER_LEN);
+       subreq = rpc_read_send(state, state->ev, state->cli->transport,
+                               state->pdu->data + RPC_HEADER_LEN,
+                               state->frag_len - RPC_HEADER_LEN);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -544,19 +584,13 @@ static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
  In fact I should probably abstract these into identical pieces of code... JRA.
  ****************************************************************************/
 
-static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
-                               prs_struct *current_pdu,
-                               uint8 *p_ss_padding_len)
+static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli,
+                                       struct ncacn_packet *pkt,
+                                       DATA_BLOB *pdu,
+                                       uint8 *p_ss_padding_len)
 {
-       RPC_HDR_AUTH auth_info;
-       uint32 save_offset = prs_offset(current_pdu);
-       uint32 auth_len = prhdr->auth_len;
-       NTLMSSP_STATE *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
-       unsigned char *data = NULL;
-       size_t data_len;
-       unsigned char *full_packet_data = NULL;
-       size_t full_packet_data_len;
-       DATA_BLOB auth_blob;
+       struct dcerpc_auth auth_info;
+       DATA_BLOB blob;
        NTSTATUS status;
 
        if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
@@ -564,91 +598,100 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
                return NT_STATUS_OK;
        }
 
-       if (!ntlmssp_state) {
+       if (!cli->auth->a_u.ntlmssp_state) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Ensure there's enough data for an authenticated response. */
-       if ((auth_len > RPC_MAX_SIGN_SIZE) ||
-                       (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
-               DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
-                       (unsigned int)auth_len ));
+       if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
+           (pkt->frag_length < DCERPC_RESPONSE_LENGTH
+                               + DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length)) {
+               DEBUG(0, ("auth_len %u is too long.\n",
+                         (unsigned int)pkt->auth_length));
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       /*
-        * We need the full packet data + length (minus auth stuff) as well as the packet data + length
-        * after the RPC header.
-        * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
-        * functions as NTLMv2 checks the rpc headers also.
-        */
-
-       data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
-       data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
+       /* get the auth blob at the end of the packet */
+       blob = data_blob_const(pdu->data + pkt->frag_length
+                               - DCERPC_AUTH_TRAILER_LENGTH
+                               - pkt->auth_length,
+                              DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length);
 
-       full_packet_data = (unsigned char *)prs_data_p(current_pdu);
-       full_packet_data_len = prhdr->frag_len - auth_len;
-
-       /* Pull the auth header and the following data into a blob. */
-       if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
-               DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
-                       (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
-               return NT_STATUS_BUFFER_TOO_SMALL;
+       status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
+               return status;
        }
 
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
-               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
+       /* Ensure auth_pad_len fits into the packet. */
+       if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
+                               + auth_info.auth_pad_length
+                               + DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
+                       "too large (%u), auth_len (%u), frag_len = (%u).\n",
+                       (unsigned int)auth_info.auth_pad_length,
+                       (unsigned int)pkt->auth_length,
+                       (unsigned int)pkt->frag_length));
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
-       auth_blob.length = auth_len;
+       /*
+        * We need the full packet data + length (minus auth stuff) as well as the packet data + length
+        * after the RPC header.
+        * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
+        * functions as NTLMv2 checks the rpc headers also.
+        */
 
        switch (cli->auth->auth_level) {
-               case DCERPC_AUTH_LEVEL_PRIVACY:
-                       /* Data is encrypted. */
-                       status = ntlmssp_unseal_packet(ntlmssp_state,
-                                                       data, data_len,
-                                                       full_packet_data,
-                                                       full_packet_data_len,
-                                                       &auth_blob);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
-                                       "packet from %s. Error was %s.\n",
-                                       rpccli_pipe_txt(debug_ctx(), cli),
-                                       nt_errstr(status) ));
-                               return status;
-                       }
-                       break;
-               case DCERPC_AUTH_LEVEL_INTEGRITY:
-                       /* Data is signed. */
-                       status = ntlmssp_check_packet(ntlmssp_state,
-                                                       data, data_len,
-                                                       full_packet_data,
-                                                       full_packet_data_len,
-                                                       &auth_blob);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
-                                       "packet from %s. Error was %s.\n",
-                                       rpccli_pipe_txt(debug_ctx(), cli),
-                                       nt_errstr(status) ));
-                               return status;
-                       }
-                       break;
-               default:
-                       DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
-                                 "auth level %d\n", cli->auth->auth_level));
-                       return NT_STATUS_INVALID_INFO_CLASS;
-       }
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               /* Data is encrypted. */
+               status = ntlmssp_unseal_packet(
+                                       cli->auth->a_u.ntlmssp_state,
+                                       pdu->data + DCERPC_RESPONSE_LENGTH,
+                                       pkt->frag_length
+                                               - DCERPC_RESPONSE_LENGTH
+                                               - DCERPC_AUTH_TRAILER_LENGTH
+                                               - pkt->auth_length,
+                                       pdu->data,
+                                       pkt->frag_length - pkt->auth_length,
+                                       &auth_info.credentials);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("failed to unseal packet from %s."
+                                 " Error was %s.\n",
+                                 rpccli_pipe_txt(talloc_tos(), cli),
+                                 nt_errstr(status)));
+                       return status;
+               }
+               break;
 
-       /*
-        * Return the current pointer to the data offset.
-        */
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+               /* Data is signed. */
+               status = ntlmssp_check_packet(
+                                       cli->auth->a_u.ntlmssp_state,
+                                       pdu->data + DCERPC_RESPONSE_LENGTH,
+                                       pkt->frag_length
+                                               - DCERPC_RESPONSE_LENGTH
+                                               - DCERPC_AUTH_TRAILER_LENGTH
+                                               - pkt->auth_length,
+                                       pdu->data,
+                                       pkt->frag_length - pkt->auth_length,
+                                       &auth_info.credentials);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("check signing failed on packet from %s."
+                                 " Error was %s.\n",
+                                 rpccli_pipe_txt(talloc_tos(), cli),
+                                 nt_errstr(status)));
+                       return status;
+               }
+               break;
 
-       if(!prs_set_offset(current_pdu, save_offset)) {
-               DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
-                       (unsigned int)save_offset ));
-               return NT_STATUS_BUFFER_TOO_SMALL;
+       default:
+               DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
+                         "auth level %d\n", cli->auth->auth_level));
+               return NT_STATUS_INVALID_INFO_CLASS;
        }
 
        /*
@@ -656,7 +699,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
         * stream once the sign/seal is done.
         */
 
-       *p_ss_padding_len = auth_info.auth_pad_len;
+       *p_ss_padding_len = auth_info.auth_pad_length;
 
        return NT_STATUS_OK;
 }
@@ -665,105 +708,120 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr
  schannel specific sign/seal.
  ****************************************************************************/
 
-static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
-                               prs_struct *current_pdu,
-                               uint8 *p_ss_padding_len)
+static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli,
+                                        struct ncacn_packet *pkt,
+                                        DATA_BLOB *pdu,
+                                        uint8 *p_ss_padding_len)
 {
-       RPC_HDR_AUTH auth_info;
-       struct NL_AUTH_SIGNATURE schannel_chk;
-       uint32 auth_len = prhdr->auth_len;
-       uint32 save_offset = prs_offset(current_pdu);
-       struct schannel_auth_struct *schannel_auth =
-               cli->auth->a_u.schannel_auth;
-       uint32 data_len;
-       enum ndr_err_code ndr_err;
+       struct dcerpc_auth auth_info;
        DATA_BLOB blob;
+       NTSTATUS status;
 
        if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
            || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
                return NT_STATUS_OK;
        }
 
-       if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
-               DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
+       if (pkt->auth_length < NL_AUTH_SIGNATURE_SIZE) {
+               DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!schannel_auth) {
+       if (!cli->auth->a_u.schannel_auth) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Ensure there's enough data for an authenticated response. */
-       if ((auth_len > RPC_MAX_SIGN_SIZE) ||
-                       (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
-               DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
-                       (unsigned int)auth_len ));
+       if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) ||
+           (pkt->frag_length < DCERPC_RESPONSE_LENGTH
+                               + DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length)) {
+               DEBUG(0, ("auth_len %u is too long.\n",
+                         (unsigned int)pkt->auth_length));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
+       /* get the auth blob at the end of the packet */
+       blob = data_blob_const(pdu->data + pkt->frag_length
+                               - DCERPC_AUTH_TRAILER_LENGTH
+                               - pkt->auth_length,
+                              DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length);
 
-       if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
-               DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
-                       (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
-               return NT_STATUS_BUFFER_TOO_SMALL;
+
+       status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
+               return status;
        }
 
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
-               DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
+       /* Ensure auth_pad_len fits into the packet. */
+       if (pkt->frag_length < DCERPC_RESPONSE_LENGTH
+                               + auth_info.auth_pad_length
+                               + DCERPC_AUTH_TRAILER_LENGTH
+                               + pkt->auth_length) {
+               DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
+                       "too large (%u), auth_len (%u), frag_len = (%u).\n",
+                       (unsigned int)auth_info.auth_pad_length,
+                       (unsigned int)pkt->auth_length,
+                       (unsigned int)pkt->frag_length));
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
        if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
-               DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
-                       auth_info.auth_type));
+               DEBUG(0, ("Invalid auth info %d on schannel\n",
+                         auth_info.auth_type));
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), data_len);
-
-       ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &schannel_chk,
-                              (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_SIGNATURE);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
-               return ndr_map_error2ntstatus(ndr_err);
+       if (DEBUGLEVEL >= 10) {
+               dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_info.credentials);
        }
 
-       if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &schannel_chk);
+       switch (cli->auth->auth_level) {
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               status = netsec_incoming_packet(
+                                       cli->auth->a_u.schannel_auth,
+                                       talloc_tos(),
+                                       true,
+                                       pdu->data + DCERPC_RESPONSE_LENGTH,
+                                       pkt->frag_length
+                                               - DCERPC_RESPONSE_LENGTH
+                                               - DCERPC_AUTH_TRAILER_LENGTH
+                                               - pkt->auth_length,
+                                       &auth_info.credentials);
+               break;
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+               status = netsec_incoming_packet(
+                                       cli->auth->a_u.schannel_auth,
+                                       talloc_tos(),
+                                       false,
+                                       pdu->data + DCERPC_RESPONSE_LENGTH,
+                                       pkt->frag_length
+                                               - DCERPC_RESPONSE_LENGTH
+                                               - DCERPC_AUTH_TRAILER_LENGTH
+                                               - pkt->auth_length,
+                                       &auth_info.credentials);
+               break;
+       default:
+               status = NT_STATUS_INTERNAL_ERROR;
+               break;
        }
 
-       if (!schannel_decode(schannel_auth,
-                       cli->auth->auth_level,
-                       SENDER_IS_ACCEPTOR,
-                       &schannel_chk,
-                       prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
-                       data_len)) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
-                               "Connection to %s.\n",
-                               rpccli_pipe_txt(debug_ctx(), cli)));
+                               "Connection to %s (%s).\n",
+                               rpccli_pipe_txt(talloc_tos(), cli),
+                               nt_errstr(status)));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* The sequence number gets incremented on both send and receive. */
-       schannel_auth->seq_num++;
-
-       /*
-        * Return the current pointer to the data offset.
-        */
-
-       if(!prs_set_offset(current_pdu, save_offset)) {
-               DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
-                       (unsigned int)save_offset ));
-               return NT_STATUS_BUFFER_TOO_SMALL;
-       }
-
        /*
         * Remember the padding length. We must remove it from the real data
         * stream once the sign/seal is done.
         */
 
-       *p_ss_padding_len = auth_info.auth_pad_len;
+       *p_ss_padding_len = auth_info.auth_pad_length;
 
        return NT_STATUS_OK;
 }
@@ -772,20 +830,25 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
  Do the authentication checks on an incoming pdu. Check sign and unseal etc.
  ****************************************************************************/
 
-static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
-                               prs_struct *current_pdu,
-                               uint8 *p_ss_padding_len)
+static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli,
+                                               struct ncacn_packet *pkt,
+                                               DATA_BLOB *pdu,
+                                               uint8 *p_ss_padding_len)
 {
        NTSTATUS ret = NT_STATUS_OK;
 
        /* Paranioa checks for auth_len. */
-       if (prhdr->auth_len) {
-               if (prhdr->auth_len > prhdr->frag_len) {
+       if (pkt->auth_length) {
+               if (pkt->auth_length > pkt->frag_length) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
-                               prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
+               if ((pkt->auth_length
+                    + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
+                                               < pkt->auth_length) ||
+                   (pkt->auth_length
+                    + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH
+                       < (unsigned int)DCERPC_AUTH_TRAILER_LENGTH)) {
                        /* Integer wrap attempt. */
                        return NT_STATUS_INVALID_PARAMETER;
                }
@@ -796,40 +859,42 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_
         */
 
        switch(cli->auth->auth_type) {
-               case PIPE_AUTH_TYPE_NONE:
-                       if (prhdr->auth_len) {
-                               DEBUG(3, ("cli_pipe_validate_rpc_response: "
-                                         "Connection to %s - got non-zero "
-                                         "auth len %u.\n",
-                                       rpccli_pipe_txt(debug_ctx(), cli),
-                                       (unsigned int)prhdr->auth_len ));
-                               return NT_STATUS_INVALID_PARAMETER;
-                       }
-                       break;
+       case PIPE_AUTH_TYPE_NONE:
+               if (pkt->auth_length) {
+                       DEBUG(3, ("cli_pipe_validate_rpc_response: "
+                                 "Connection to %s - got non-zero "
+                                 "auth len %u.\n",
+                               rpccli_pipe_txt(talloc_tos(), cli),
+                               (unsigned int)pkt->auth_length));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               break;
 
-               case PIPE_AUTH_TYPE_NTLMSSP:
-               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-                       ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
-                       if (!NT_STATUS_IS_OK(ret)) {
-                               return ret;
-                       }
-                       break;
+       case PIPE_AUTH_TYPE_NTLMSSP:
+       case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+               ret = cli_pipe_verify_ntlmssp(cli, pkt, pdu,
+                                               p_ss_padding_len);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
+               break;
 
-               case PIPE_AUTH_TYPE_SCHANNEL:
-                       ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
-                       if (!NT_STATUS_IS_OK(ret)) {
-                               return ret;
-                       }
-                       break;
+       case PIPE_AUTH_TYPE_SCHANNEL:
+               ret = cli_pipe_verify_schannel(cli, pkt, pdu,
+                                               p_ss_padding_len);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
+               break;
 
-               case PIPE_AUTH_TYPE_KRB5:
-               case PIPE_AUTH_TYPE_SPNEGO_KRB5:
-               default:
-                       DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
-                                 "to %s - unknown internal auth type %u.\n",
-                                 rpccli_pipe_txt(debug_ctx(), cli),
-                                 cli->auth->auth_type ));
-                       return NT_STATUS_INVALID_INFO_CLASS;
+       case PIPE_AUTH_TYPE_KRB5:
+       case PIPE_AUTH_TYPE_SPNEGO_KRB5:
+       default:
+               DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
+                         "to %s - unknown internal auth type %u.\n",
+                         rpccli_pipe_txt(talloc_tos(), cli),
+                         cli->auth->auth_type ));
+               return NT_STATUS_INVALID_INFO_CLASS;
        }
 
        return NT_STATUS_OK;
@@ -839,20 +904,26 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_
  Do basic authentication checks on an incoming pdu.
  ****************************************************************************/
 
-static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
-                       prs_struct *current_pdu,
-                       uint8 expected_pkt_type,
-                       char **ppdata,
-                       uint32 *pdata_len,
-                       prs_struct *return_data)
+static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
+                                               struct rpc_pipe_client *cli,
+                                               struct ncacn_packet *pkt,
+                                               DATA_BLOB *pdu,
+                                               uint8_t expected_pkt_type,
+                                               DATA_BLOB *rdata,
+                                               DATA_BLOB *reply_pdu)
 {
-
        NTSTATUS ret = NT_STATUS_OK;
-       uint32 current_pdu_len = prs_data_size(current_pdu);
+       uint8 ss_padding_len = 0;
+
+       ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false);
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
 
-       if (current_pdu_len != prhdr->frag_len) {
-               DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
-                       (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
+       if (pdu->length != pkt->frag_length) {
+               DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
+                         (unsigned int)pdu->length,
+                         (unsigned int)pkt->frag_length));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -860,120 +931,108 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
         * Point the return values at the real data including the RPC
         * header. Just in case the caller wants it.
         */
-       *ppdata = prs_data_p(current_pdu);
-       *pdata_len = current_pdu_len;
+       *rdata = *pdu;
 
        /* Ensure we have the correct type. */
-       switch (prhdr->pkt_type) {
-               case RPC_ALTCONTRESP:
-               case RPC_BINDACK:
-
-                       /* Alter context and bind ack share the same packet definitions. */
-                       break;
+       switch (pkt->ptype) {
+       case DCERPC_PKT_ALTER_RESP:
+       case DCERPC_PKT_BIND_ACK:
 
+               /* Alter context and bind ack share the same packet definitions. */
+               break;
 
-               case RPC_RESPONSE:
-               {
-                       RPC_HDR_RESP rhdr_resp;
-                       uint8 ss_padding_len = 0;
 
-                       if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
-                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
-                               return NT_STATUS_BUFFER_TOO_SMALL;
-                       }
+       case DCERPC_PKT_RESPONSE:
 
-                       /* Here's where we deal with incoming sign/seal. */
-                       ret = cli_pipe_validate_rpc_response(cli, prhdr,
-                                       current_pdu, &ss_padding_len);
-                       if (!NT_STATUS_IS_OK(ret)) {
-                               return ret;
-                       }
+               /* Here's where we deal with incoming sign/seal. */
+               ret = cli_pipe_validate_rpc_response(cli, pkt, pdu,
+                                                    &ss_padding_len);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
 
-                       /* Point the return values at the NDR data. Remember to remove any ss padding. */
-                       *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
+               /* Point the return values at the NDR data.
+                * Remember to remove any ss padding. */
+               rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH;
 
-                       if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
-                               return NT_STATUS_BUFFER_TOO_SMALL;
-                       }
+               if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) {
+                       return NT_STATUS_BUFFER_TOO_SMALL;
+               }
 
-                       *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
+               rdata->length = pdu->length
+                                       - DCERPC_RESPONSE_LENGTH
+                                       - ss_padding_len;
 
-                       /* Remember to remove the auth footer. */
-                       if (prhdr->auth_len) {
-                               /* We've already done integer wrap tests on auth_len in
-                                       cli_pipe_validate_rpc_response(). */
-                               if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
-                                       return NT_STATUS_BUFFER_TOO_SMALL;
-                               }
-                               *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
-                       }
-
-                       DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
-                               current_pdu_len, *pdata_len, ss_padding_len ));
-
-                       /*
-                        * If this is the first reply, and the allocation hint is reasonably, try and
-                        * set up the return_data parse_struct to the correct size.
-                        */
-
-                       if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
-                               if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
-                                       DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
-                                               "too large to allocate\n",
-                                               (unsigned int)rhdr_resp.alloc_hint ));
-                                       return NT_STATUS_NO_MEMORY;
-                               }
+               /* Remember to remove the auth footer. */
+               if (pkt->auth_length) {
+                       /* We've already done integer wrap tests on auth_len in
+                               cli_pipe_validate_rpc_response(). */
+                       if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH
+                                                       + pkt->auth_length) {
+                               return NT_STATUS_BUFFER_TOO_SMALL;
                        }
-
-                       break;
+                       rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH
+                                                       + pkt->auth_length);
                }
 
-               case RPC_BINDNACK:
-                       DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
-                                 "received from %s!\n",
-                                 rpccli_pipe_txt(debug_ctx(), cli)));
-                       /* Use this for now... */
-                       return NT_STATUS_NETWORK_ACCESS_DENIED;
+               DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
+                          (long unsigned int)pdu->length,
+                          (long unsigned int)rdata->length,
+                          (long unsigned int)ss_padding_len));
 
-               case RPC_FAULT:
-               {
-                       RPC_HDR_RESP rhdr_resp;
-                       RPC_HDR_FAULT fault_resp;
+               /*
+                * If this is the first reply, and the allocation hint is
+                * reasonable, try and set up the reply_pdu DATA_BLOB to the
+                * correct size.
+                */
 
-                       if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
-                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
-                               return NT_STATUS_BUFFER_TOO_SMALL;
+               if ((reply_pdu->length == 0) &&
+                   pkt->u.response.alloc_hint &&
+                   (pkt->u.response.alloc_hint < 15*1024*1024)) {
+                       if (!data_blob_realloc(mem_ctx, reply_pdu,
+                                               pkt->u.response.alloc_hint)) {
+                               DEBUG(0, ("reply alloc hint %d too "
+                                         "large to allocate\n",
+                                   (int)pkt->u.response.alloc_hint));
+                               return NT_STATUS_NO_MEMORY;
                        }
+               }
 
-                       if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
-                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
-                               return NT_STATUS_BUFFER_TOO_SMALL;
-                       }
+               break;
 
-                       DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
-                                 "code %s received from %s!\n",
-                               dcerpc_errstr(debug_ctx(), NT_STATUS_V(fault_resp.status)),
-                               rpccli_pipe_txt(debug_ctx(), cli)));
-                       if (NT_STATUS_IS_OK(fault_resp.status)) {
-                               return NT_STATUS_UNSUCCESSFUL;
-                       } else {
-                               return fault_resp.status;
-                       }
+       case DCERPC_PKT_BIND_NAK:
+               DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
+                         "received from %s!\n",
+                         rpccli_pipe_txt(talloc_tos(), cli)));
+               /* Use this for now... */
+               return NT_STATUS_NETWORK_ACCESS_DENIED;
+
+       case DCERPC_PKT_FAULT:
+
+               DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
+                         "code %s received from %s!\n",
+                         dcerpc_errstr(talloc_tos(),
+                         pkt->u.fault.status),
+                       rpccli_pipe_txt(talloc_tos(), cli)));
+
+               if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               } else {
+                       return NT_STATUS(pkt->u.fault.status);
                }
 
-               default:
-                       DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
-                               "from %s!\n",
-                               (unsigned int)prhdr->pkt_type,
-                               rpccli_pipe_txt(debug_ctx(), cli)));
-                       return NT_STATUS_INVALID_INFO_CLASS;
+       default:
+               DEBUG(0, ("Unknown packet type %u received from %s!\n",
+                       (unsigned int)pkt->ptype,
+                       rpccli_pipe_txt(talloc_tos(), cli)));
+               return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       if (prhdr->pkt_type != expected_pkt_type) {
+       if (pkt->ptype != expected_pkt_type) {
                DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
                          "got an unexpected RPC packet type - %u, not %u\n",
-                       rpccli_pipe_txt(debug_ctx(), cli),
-                       prhdr->pkt_type,
+                       rpccli_pipe_txt(talloc_tos(), cli),
+                       pkt->ptype,
                        expected_pkt_type));
                return NT_STATUS_INVALID_INFO_CLASS;
        }
@@ -982,53 +1041,12 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
           data before now as we may have needed to do cryptographic actions on
           it before. */
 
-       if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
+       if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
+           !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
                DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
                        "setting fragment first/last ON.\n"));
-               prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
-       }
-
-       return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Ensure we eat the just processed pdu from the current_pdu prs_struct.
- Normally the frag_len and buffer size will match, but on the first trans
- reply there is a theoretical chance that buffer size > frag_len, so we must
- deal with that.
- ****************************************************************************/
-
-static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
-{
-       uint32 current_pdu_len = prs_data_size(current_pdu);
-
-       if (current_pdu_len < prhdr->frag_len) {
-               return NT_STATUS_BUFFER_TOO_SMALL;
-       }
-
-       /* Common case. */
-       if (current_pdu_len == (uint32)prhdr->frag_len) {
-               prs_mem_free(current_pdu);
-               prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
-               /* Make current_pdu dynamic with no memory. */
-               prs_give_memory(current_pdu, 0, 0, True);
-               return NT_STATUS_OK;
-       }
-
-       /*
-        * Oh no ! More data in buffer than we processed in current pdu.
-        * Cheat. Move the data down and shrink the buffer.
-        */
-
-       memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
-                       current_pdu_len - prhdr->frag_len);
-
-       /* Remember to set the read offset back to zero. */
-       prs_set_offset(current_pdu, 0);
-
-       /* Shrink the buffer. */
-       if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
-               return NT_STATUS_BUFFER_TOO_SMALL;
+               pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST |
+                                       DCERPC_PFC_FLAG_LAST;
        }
 
        return NT_STATUS_OK;
@@ -1098,8 +1116,6 @@ static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
        tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
        return req;
 
-       status = NT_STATUS_INVALID_PARAMETER;
-
  post_status:
        tevent_req_nterror(req, status);
        return tevent_req_post(req, ev);
@@ -1196,7 +1212,7 @@ static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 }
 
 /****************************************************************************
- Send data on an rpc pipe via trans. The prs_struct data must be the last
+ Send data on an rpc pipe via trans. The data must be the last
  pdu fragment of an NDR data stream.
 
  Receive response data from an rpc pipe, which may be large...
@@ -1226,27 +1242,22 @@ struct rpc_api_pipe_state {
        struct rpc_pipe_client *cli;
        uint8_t expected_pkt_type;
 
-       prs_struct incoming_frag;
-       struct rpc_hdr_info rhdr;
+       DATA_BLOB incoming_frag;
+       struct ncacn_packet *pkt;
 
-       prs_struct incoming_pdu;        /* Incoming reply */
-       uint32_t incoming_pdu_offset;
+       /* Incoming reply */
+       DATA_BLOB reply_pdu;
+       size_t reply_pdu_offset;
+       uint8_t endianess;
 };
 
-static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
-{
-       prs_mem_free(&state->incoming_frag);
-       prs_mem_free(&state->incoming_pdu);
-       return 0;
-}
-
 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
 
 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
                                            struct event_context *ev,
                                            struct rpc_pipe_client *cli,
-                                           prs_struct *data, /* Outgoing PDU */
+                                           DATA_BLOB *data, /* Outgoing PDU */
                                            uint8_t expected_pkt_type)
 {
        struct tevent_req *req, *subreq;
@@ -1261,35 +1272,27 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
        state->ev = ev;
        state->cli = cli;
        state->expected_pkt_type = expected_pkt_type;
-       state->incoming_pdu_offset = 0;
-
-       prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
-
-       prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
-       /* Make incoming_pdu dynamic with no memory. */
-       prs_give_memory(&state->incoming_pdu, NULL, 0, true);
-
-       talloc_set_destructor(state, rpc_api_pipe_state_destructor);
+       state->incoming_frag = data_blob_null;
+       state->reply_pdu = data_blob_null;
+       state->reply_pdu_offset = 0;
+       state->endianess = DCERPC_DREP_LE;
 
        /*
         * Ensure we're not sending too much.
         */
-       if (prs_offset(data) > cli->max_xmit_frag) {
+       if (data->length > cli->max_xmit_frag) {
                status = NT_STATUS_INVALID_PARAMETER;
                goto post_status;
        }
 
-       DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(debug_ctx(), cli)));
+       DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
 
-       max_recv_frag = cli->max_recv_frag;
-
-#ifdef DEVELOPER
-       max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
-#endif
+       /* get the header first, then fetch the rest once we have
+        * the frag_length available */
+       max_recv_frag = RPC_HEADER_LEN;
 
        subreq = cli_api_pipe_send(state, ev, cli->transport,
-                                  (uint8_t *)prs_data_p(data),
-                                  prs_offset(data), max_recv_frag);
+                                  data->data, data->length, max_recv_frag);
        if (subreq == NULL) {
                goto fail;
        }
@@ -1313,7 +1316,6 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
        NTSTATUS status;
        uint8_t *rdata = NULL;
        uint32_t rdata_len = 0;
-       char *rdata_copy;
 
        status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
        TALLOC_FREE(subreq);
@@ -1325,26 +1327,24 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
 
        if (rdata == NULL) {
                DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
-                        rpccli_pipe_txt(debug_ctx(), state->cli)));
+                        rpccli_pipe_txt(talloc_tos(), state->cli)));
                tevent_req_done(req);
                return;
        }
 
        /*
-        * Give the memory received from cli_trans as dynamic to the current
-        * pdu. Duplicating it sucks, but prs_struct doesn't know about talloc
-        * :-(
+        * Move data on state->incoming_frag.
         */
-       rdata_copy = (char *)memdup(rdata, rdata_len);
-       TALLOC_FREE(rdata);
-       if (tevent_req_nomem(rdata_copy, req)) {
+       state->incoming_frag.data = talloc_move(state, &rdata);
+       state->incoming_frag.length = rdata_len;
+       if (!state->incoming_frag.data) {
+               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
-       prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true);
 
        /* Ensure we have enough data for a pdu. */
        subreq = get_complete_frag_send(state, state->ev, state->cli,
-                                       &state->rhdr, &state->incoming_frag);
+                                       &state->incoming_frag);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -1358,8 +1358,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
        struct rpc_api_pipe_state *state = tevent_req_data(
                req, struct rpc_api_pipe_state);
        NTSTATUS status;
-       char *rdata = NULL;
-       uint32_t rdata_len = 0;
+       DATA_BLOB rdata = data_blob_null;
 
        status = get_complete_frag_recv(subreq);
        TALLOC_FREE(subreq);
@@ -1370,14 +1369,22 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
                return;
        }
 
-       status = cli_pipe_validate_current_pdu(
-               state->cli, &state->rhdr, &state->incoming_frag,
-               state->expected_pkt_type, &rdata, &rdata_len,
-               &state->incoming_pdu);
+       state->pkt = talloc(state, struct ncacn_packet);
+       if (!state->pkt) {
+               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+
+       status = cli_pipe_validate_current_pdu(state,
+                                               state->cli, state->pkt,
+                                               &state->incoming_frag,
+                                               state->expected_pkt_type,
+                                               &rdata,
+                                               &state->reply_pdu);
 
        DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
-                 (unsigned)prs_data_size(&state->incoming_frag),
-                 (unsigned)state->incoming_pdu_offset,
+                 (unsigned)state->incoming_frag.length,
+                 (unsigned)state->reply_pdu_offset,
                  nt_errstr(status)));
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -1385,57 +1392,61 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
                return;
        }
 
-       if ((state->rhdr.flags & RPC_FLG_FIRST)
-           && (state->rhdr.pack_type[0] == 0)) {
+       if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
+           && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
                /*
                 * Set the data type correctly for big-endian data on the
                 * first packet.
                 */
                DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
                          "big-endian.\n",
-                         rpccli_pipe_txt(debug_ctx(), state->cli)));
-               prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
+                         rpccli_pipe_txt(talloc_tos(), state->cli)));
+               state->endianess = 0x00; /* BIG ENDIAN */
        }
        /*
         * Check endianness on subsequent packets.
         */
-       if (state->incoming_frag.bigendian_data
-           != state->incoming_pdu.bigendian_data) {
+       if (state->endianess != state->pkt->drep[0]) {
                DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
                         "%s\n",
-                        state->incoming_pdu.bigendian_data?"big":"little",
-                        state->incoming_frag.bigendian_data?"big":"little"));
+                        state->endianess?"little":"big",
+                        state->pkt->drep[0]?"little":"big"));
                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
 
        /* Now copy the data portion out of the pdu into rbuf. */
-       if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
-               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
+       if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
+               if (!data_blob_realloc(NULL, &state->reply_pdu,
+                               state->reply_pdu_offset + rdata.length)) {
+                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
        }
 
-       memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
-              rdata, (size_t)rdata_len);
-       state->incoming_pdu_offset += rdata_len;
+       memcpy(state->reply_pdu.data + state->reply_pdu_offset,
+               rdata.data, rdata.length);
+       state->reply_pdu_offset += rdata.length;
 
-       status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
-                                           &state->incoming_frag);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
-       }
+       /* reset state->incoming_frag, there is no need to free it,
+        * it will be reallocated to the right size the next time
+        * it is used */
+       state->incoming_frag.length = 0;
 
-       if (state->rhdr.flags & RPC_FLG_LAST) {
+       if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
+               /* make sure the pdu length is right now that we
+                * have all the data available (alloc hint may
+                * have allocated more than was actually used) */
+               state->reply_pdu.length = state->reply_pdu_offset;
                DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
-                         rpccli_pipe_txt(debug_ctx(), state->cli),
-                         (unsigned)prs_data_size(&state->incoming_pdu)));
+                         rpccli_pipe_txt(talloc_tos(), state->cli),
+                         (unsigned)state->reply_pdu.length));
                tevent_req_done(req);
                return;
        }
 
        subreq = get_complete_frag_send(state, state->ev, state->cli,
-                                       &state->rhdr, &state->incoming_frag);
+                                       &state->incoming_frag);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -1443,7 +1454,8 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
 }
 
 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                                 prs_struct *reply_pdu)
+                                 struct ncacn_packet **pkt,
+                                 DATA_BLOB *reply_pdu)
 {
        struct rpc_api_pipe_state *state = tevent_req_data(
                req, struct rpc_api_pipe_state);
@@ -1453,14 +1465,18 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       *reply_pdu = state->incoming_pdu;
-       reply_pdu->mem_ctx = mem_ctx;
+       /* return data to caller and assign it ownership of memory */
+       if (reply_pdu) {
+               reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
+               reply_pdu->length = state->reply_pdu.length;
+               state->reply_pdu.length = 0;
+       } else {
+               data_blob_free(&state->reply_pdu);
+       }
 
-       /*
-        * Prevent state->incoming_pdu from being freed in
-        * rpc_api_pipe_state_destructor()
-        */
-       prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
+       if (pkt) {
+               *pkt = talloc_steal(mem_ctx, state->pkt);
+       }
 
        return NT_STATUS_OK;
 }
@@ -1469,27 +1485,24 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
  Creates krb5 auth bind.
  ********************************************************************/
 
-static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
-                                               enum dcerpc_AuthLevel auth_level,
-                                               RPC_HDR_AUTH *pauth_out,
-                                               prs_struct *auth_data)
+static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
+                                         enum dcerpc_AuthLevel auth_level,
+                                         DATA_BLOB *auth_info)
 {
 #ifdef HAVE_KRB5
        int ret;
+       NTSTATUS status;
        struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
        DATA_BLOB tkt = data_blob_null;
        DATA_BLOB tkt_wrapped = data_blob_null;
 
-       /* We may change the pad length before marshalling. */
-       init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
-
        DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
                a->service_principal ));
 
        /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
 
        ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
-                       &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
+                       &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
 
        if (ret) {
                DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
@@ -1498,7 +1511,6 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
                        error_message(ret) ));
 
                data_blob_free(&tkt);
-               prs_mem_free(auth_data);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -1507,17 +1519,21 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
 
        data_blob_free(&tkt);
 
-       /* Auth len in the rpc header doesn't include auth_header. */
-       if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
+       status = dcerpc_push_dcerpc_auth(cli,
+                                        DCERPC_AUTH_TYPE_KRB5,
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        &tkt_wrapped,
+                                        auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
                data_blob_free(&tkt_wrapped);
-               prs_mem_free(auth_data);
-               return NT_STATUS_NO_MEMORY;
+               return status;
        }
 
        DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
        dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
 
-       data_blob_free(&tkt_wrapped);
        return NT_STATUS_OK;
 #else
        return NT_STATUS_INVALID_PARAMETER;
@@ -1528,28 +1544,23 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
  Creates SPNEGO NTLMSSP auth bind.
  ********************************************************************/
 
-static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
-                                               enum dcerpc_AuthLevel auth_level,
-                                               RPC_HDR_AUTH *pauth_out,
-                                               prs_struct *auth_data)
+static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
+                                                       enum dcerpc_AuthLevel auth_level,
+                                                       DATA_BLOB *auth_info)
 {
-       NTSTATUS nt_status;
+       NTSTATUS status;
        DATA_BLOB null_blob = data_blob_null;
        DATA_BLOB request = data_blob_null;
        DATA_BLOB spnego_msg = data_blob_null;
 
-       /* We may change the pad length before marshalling. */
-       init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
-
        DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
-       nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
+       status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
                                        null_blob,
                                        &request);
 
-       if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                data_blob_free(&request);
-               prs_mem_free(auth_data);
-               return nt_status;
+               return status;
        }
 
        /* Wrap this in SPNEGO. */
@@ -1557,17 +1568,21 @@ static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client
 
        data_blob_free(&request);
 
-       /* Auth len in the rpc header doesn't include auth_header. */
-       if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
+       status = dcerpc_push_dcerpc_auth(cli,
+                                        DCERPC_AUTH_TYPE_SPNEGO,
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        &spnego_msg,
+                                        auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
                data_blob_free(&spnego_msg);
-               prs_mem_free(auth_data);
-               return NT_STATUS_NO_MEMORY;
+               return status;
        }
 
        DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
        dump_data(5, spnego_msg.data, spnego_msg.length);
 
-       data_blob_free(&spnego_msg);
        return NT_STATUS_OK;
 }
 
@@ -1575,40 +1590,39 @@ static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client
  Creates NTLMSSP auth bind.
  ********************************************************************/
 
-static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
-                                               enum dcerpc_AuthLevel auth_level,
-                                               RPC_HDR_AUTH *pauth_out,
-                                               prs_struct *auth_data)
+static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
+                                                enum dcerpc_AuthLevel auth_level,
+                                                DATA_BLOB *auth_info)
 {
-       NTSTATUS nt_status;
+       NTSTATUS status;
        DATA_BLOB null_blob = data_blob_null;
        DATA_BLOB request = data_blob_null;
 
-       /* We may change the pad length before marshalling. */
-       init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
-
        DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
-       nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
+       status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
                                        null_blob,
                                        &request);
 
-       if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                data_blob_free(&request);
-               prs_mem_free(auth_data);
-               return nt_status;
+               return status;
        }
 
-       /* Auth len in the rpc header doesn't include auth_header. */
-       if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
+       status = dcerpc_push_dcerpc_auth(cli,
+                                        DCERPC_AUTH_TYPE_NTLMSSP,
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        &request,
+                                        auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
                data_blob_free(&request);
-               prs_mem_free(auth_data);
-               return NT_STATUS_NO_MEMORY;
+               return status;
        }
 
        DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
        dump_data(5, request.data, request.length);
 
-       data_blob_free(&request);
        return NT_STATUS_OK;
 }
 
@@ -1616,17 +1630,13 @@ static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
  Creates schannel auth bind.
  ********************************************************************/
 
-static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
-                                               enum dcerpc_AuthLevel auth_level,
-                                               RPC_HDR_AUTH *pauth_out,
-                                               prs_struct *auth_data)
+static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
+                                                 enum dcerpc_AuthLevel auth_level,
+                                                 DATA_BLOB *auth_info)
 {
+       NTSTATUS status;
        struct NL_AUTH_MESSAGE r;
-       enum ndr_err_code ndr_err;
-       DATA_BLOB blob;
-
-       /* We may change the pad length before marshalling. */
-       init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
+       DATA_BLOB schannel_blob;
 
        /* Use lp_workgroup() if domain not specified */
 
@@ -1647,22 +1657,20 @@ static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
        r.oem_netbios_domain.a          = cli->auth->domain;
        r.oem_netbios_computer.a        = global_myname();
 
-       ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &r,
-                      (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
-               prs_mem_free(auth_data);
-               return ndr_map_error2ntstatus(ndr_err);
-       }
-
-       if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
+       status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
-       {
-               prs_mem_free(auth_data);
-               return NT_STATUS_NO_MEMORY;
+       status = dcerpc_push_dcerpc_auth(cli,
+                                        DCERPC_AUTH_TYPE_SCHANNEL,
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        &schannel_blob,
+                                        auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        return NT_STATUS_OK;
@@ -1672,79 +1680,46 @@ static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
  Creates the internals of a DCE/RPC bind request or alter context PDU.
  ********************************************************************/
 
-static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
-                                               prs_struct *rpc_out, 
+static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
+                                               enum dcerpc_pkt_type ptype,
                                                uint32 rpc_call_id,
                                                const struct ndr_syntax_id *abstract,
                                                const struct ndr_syntax_id *transfer,
-                                               RPC_HDR_AUTH *phdr_auth,
-                                               prs_struct *pauth_info)
+                                               const DATA_BLOB *auth_info,
+                                               DATA_BLOB *blob)
 {
-       RPC_HDR hdr;
-       RPC_HDR_RB hdr_rb;
-       RPC_CONTEXT rpc_ctx;
-       uint16 auth_len = prs_offset(pauth_info);
-       uint8 ss_padding_len = 0;
-       uint16 frag_len = 0;
-
-       /* create the RPC context. */
-       init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
-
-       /* create the bind request RPC_HDR_RB */
-       init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
-
-       /* Start building the frag length. */
-       frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
+       uint16 auth_len = auth_info->length;
+       NTSTATUS status;
+       union dcerpc_payload u;
+       struct dcerpc_ctx_list ctx_list;
 
-       /* Do we need to pad ? */
        if (auth_len) {
-               uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
-               if (data_len % 8) {
-                       ss_padding_len = 8 - (data_len % 8);
-                       phdr_auth->auth_pad_len = ss_padding_len;
-               }
-               frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
-       }
-
-       /* Create the request RPC_HDR */
-       init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
-
-       /* Marshall the RPC header */
-       if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
-               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* Marshall the bind request data */
-       if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
-               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /*
-        * Grow the outgoing buffer to store any auth info.
-        */
-
-       if(auth_len != 0) {
-               if (ss_padding_len) {
-                       char pad[8];
-                       memset(pad, '\0', 8);
-                       if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
-                               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-
-               if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
-                       DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-
-               if(!prs_append_prs_data( rpc_out, pauth_info)) {
-                       DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
-                       return NT_STATUS_NO_MEMORY;
-               }
+               auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
+       }
+
+       ctx_list.context_id = 0;
+       ctx_list.num_transfer_syntaxes = 1;
+       ctx_list.abstract_syntax = *abstract;
+       ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
+
+       u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
+       u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
+       u.bind.assoc_group_id   = 0x0;
+       u.bind.num_contexts     = 1;
+       u.bind.ctx_list         = &ctx_list;
+       u.bind.auth_info        = *auth_info;
+
+       status = dcerpc_push_ncacn_packet(mem_ctx,
+                                         ptype,
+                                         DCERPC_PFC_FLAG_FIRST |
+                                         DCERPC_PFC_FLAG_LAST,
+                                         auth_len,
+                                         rpc_call_id,
+                                         &u,
+                                         blob);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
+               return status;
        }
 
        return NT_STATUS_OK;
@@ -1754,51 +1729,43 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
  Creates a DCE/RPC bind request.
  ********************************************************************/
 
-static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
-                               prs_struct *rpc_out, 
-                               uint32 rpc_call_id,
-                               const struct ndr_syntax_id *abstract,
-                               const struct ndr_syntax_id *transfer,
-                               enum pipe_auth_type auth_type,
-                               enum dcerpc_AuthLevel auth_level)
+static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
+                                   struct rpc_pipe_client *cli,
+                                   uint32 rpc_call_id,
+                                   const struct ndr_syntax_id *abstract,
+                                   const struct ndr_syntax_id *transfer,
+                                   enum pipe_auth_type auth_type,
+                                   enum dcerpc_AuthLevel auth_level,
+                                   DATA_BLOB *rpc_out)
 {
-       RPC_HDR_AUTH hdr_auth;
-       prs_struct auth_info;
+       DATA_BLOB auth_info = data_blob_null;
        NTSTATUS ret = NT_STATUS_OK;
 
-       ZERO_STRUCT(hdr_auth);
-       if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
-               return NT_STATUS_NO_MEMORY;
-
        switch (auth_type) {
                case PIPE_AUTH_TYPE_SCHANNEL:
-                       ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
                        if (!NT_STATUS_IS_OK(ret)) {
-                               prs_mem_free(&auth_info);
                                return ret;
                        }
                        break;
 
                case PIPE_AUTH_TYPE_NTLMSSP:
-                       ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
                        if (!NT_STATUS_IS_OK(ret)) {
-                               prs_mem_free(&auth_info);
                                return ret;
                        }
                        break;
 
                case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-                       ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
                        if (!NT_STATUS_IS_OK(ret)) {
-                               prs_mem_free(&auth_info);
                                return ret;
                        }
                        break;
 
                case PIPE_AUTH_TYPE_KRB5:
-                       ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
                        if (!NT_STATUS_IS_OK(ret)) {
-                               prs_mem_free(&auth_info);
                                return ret;
                        }
                        break;
@@ -1811,15 +1778,13 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
                        return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       ret = create_bind_or_alt_ctx_internal(RPC_BIND,
-                                               rpc_out, 
-                                               rpc_call_id,
-                                               abstract,
-                                               transfer,
-                                               &hdr_auth,
-                                               &auth_info);
-
-       prs_mem_free(&auth_info);
+       ret = create_bind_or_alt_ctx_internal(mem_ctx,
+                                             DCERPC_PKT_BIND,
+                                             rpc_call_id,
+                                             abstract,
+                                             transfer,
+                                             &auth_info,
+                                             rpc_out);
        return ret;
 }
 
@@ -1828,79 +1793,88 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
  ********************************************************************/
 
 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
-                                       RPC_HDR *phdr,
                                        uint32 ss_padding_len,
-                                       prs_struct *outgoing_pdu)
+                                       DATA_BLOB *rpc_out)
 {
-       RPC_HDR_AUTH auth_info;
+       DATA_BLOB auth_info;
        NTSTATUS status;
        DATA_BLOB auth_blob = data_blob_null;
-       uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
+       uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
 
        if (!cli->auth->a_u.ntlmssp_state) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* Init and marshall the auth header. */
-       init_rpc_hdr_auth(&auth_info,
-                       map_pipe_auth_type_to_rpc_auth_type(
-                               cli->auth->auth_type),
-                       cli->auth->auth_level,
-                       ss_padding_len,
-                       1 /* context id. */);
+       /* marshall the dcerpc_auth with an actually empty auth_blob.
+        * this is needed because the ntmlssp signature includes the
+        * auth header */
+       status = dcerpc_push_dcerpc_auth(rpc_out->data,
+                                       map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
+                                       cli->auth->auth_level,
+                                       ss_padding_len,
+                                       1 /* context id. */,
+                                       &auth_blob,
+                                       &auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
-               DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
-               data_blob_free(&auth_blob);
+       /* 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);
 
        switch (cli->auth->auth_level) {
-               case DCERPC_AUTH_LEVEL_PRIVACY:
-                       /* Data portion is encrypted. */
-                       status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
-                                       (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
-                                       data_and_pad_len,
-                                       (unsigned char *)prs_data_p(outgoing_pdu),
-                                       (size_t)prs_offset(outgoing_pdu),
-                                       &auth_blob);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
-                               return status;
-                       }
-                       break;
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               /* Data portion is encrypted. */
+               status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_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 = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
-                                       (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
-                                       data_and_pad_len,
-                                       (unsigned char *)prs_data_p(outgoing_pdu),
-                                       (size_t)prs_offset(outgoing_pdu),
-                                       &auth_blob);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
-                               return status;
-                       }
-                       break;
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+               /* Data is signed. */
+               status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_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;
+       default:
+               /* Can't happen. */
+               smb_panic("bad auth level");
+               /* Notreached. */
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* Finally marshall the blob. */
-
-       if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
-               DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
-                       (unsigned int)NTLMSSP_SIG_SIZE));
-               data_blob_free(&auth_blob);
+       /* 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_info.length));
                return NT_STATUS_NO_MEMORY;
        }
-
        data_blob_free(&auth_blob);
+
        return NT_STATUS_OK;
 }
 
@@ -1909,71 +1883,74 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
  ********************************************************************/
 
 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
-                                       RPC_HDR *phdr,
                                        uint32 ss_padding_len,
-                                       prs_struct *outgoing_pdu)
+                                       DATA_BLOB *rpc_out)
 {
-       RPC_HDR_AUTH auth_info;
-       struct NL_AUTH_SIGNATURE verf;
-       struct schannel_auth_struct *sas = cli->auth->a_u.schannel_auth;
-       char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
-       size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
-       enum ndr_err_code ndr_err;
+       DATA_BLOB auth_info;
+       struct schannel_state *sas = cli->auth->a_u.schannel_auth;
+       uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
+       size_t data_and_pad_len = rpc_out->length
+                                       - DCERPC_RESPONSE_LENGTH;
        DATA_BLOB blob;
+       NTSTATUS status;
 
        if (!sas) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* Init and marshall the auth header. */
-       init_rpc_hdr_auth(&auth_info,
-                       map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
-                       cli->auth->auth_level,
-                       ss_padding_len,
-                       1 /* context id. */);
-
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
-               DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
+       DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
+                       sas->seq_num));
 
        switch (cli->auth->auth_level) {
-               case DCERPC_AUTH_LEVEL_PRIVACY:
-               case DCERPC_AUTH_LEVEL_INTEGRITY:
-                       DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
-                               sas->seq_num));
-
-                       schannel_encode(sas,
-                                       cli->auth->auth_level,
-                                       SENDER_IS_INITIATOR,
-                                       &verf,
-                                       data_p,
-                                       data_and_pad_len);
-
-                       sas->seq_num++;
-                       break;
-
-               default:
-                       /* Can't happen. */
-                       smb_panic("bad auth level");
-                       /* Notreached. */
-                       return NT_STATUS_INVALID_PARAMETER;
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               status = netsec_outgoing_packet(sas,
+                                               rpc_out->data,
+                                               true,
+                                               data_p,
+                                               data_and_pad_len,
+                                               &blob);
+               break;
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+               status = netsec_outgoing_packet(sas,
+                                               rpc_out->data,
+                                               false,
+                                               data_p,
+                                               data_and_pad_len,
+                                               &blob);
+               break;
+       default:
+               status = NT_STATUS_INTERNAL_ERROR;
+               break;
        }
 
-       ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &verf,
-                              (ndr_push_flags_fn_t)ndr_push_NL_AUTH_SIGNATURE);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               return ndr_map_error2ntstatus(ndr_err);
+       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) {
-               NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &verf);
+               dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
        }
 
        /* Finally marshall the blob. */
-       if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
+       status = dcerpc_push_dcerpc_auth(rpc_out->data,
+                  map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
+                                       cli->auth->auth_level,
+                                       ss_padding_len,
+                                       1 /* context id. */,
+                                       &blob,
+                                       &auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       data_blob_free(&blob);
+
+       if (!data_blob_append(NULL, rpc_out,
+                               auth_info.data, auth_info.length)) {
                return NT_STATUS_NO_MEMORY;
        }
+       data_blob_free(&auth_info);
 
        return NT_STATUS_OK;
 }
@@ -1991,7 +1968,7 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
 {
        uint32 data_space, data_len;
 
-#ifdef DEVELOPER
+#if 0
        if ((data_left > 0) && (sys_random() % 2)) {
                data_left = MAX(data_left/2, 1);
        }
@@ -2000,11 +1977,11 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
        switch (cli->auth->auth_level) {
                case DCERPC_AUTH_LEVEL_NONE:
                case DCERPC_AUTH_LEVEL_CONNECT:
-                       data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
+                       data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
                        data_len = MIN(data_space, data_left);
                        *p_ss_padding = 0;
                        *p_auth_len = 0;
-                       *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
+                       *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
                        return data_len;
 
                case DCERPC_AUTH_LEVEL_INTEGRITY:
@@ -2016,24 +1993,27 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
                                        *p_auth_len = NTLMSSP_SIG_SIZE;
                                        break;
                                case PIPE_AUTH_TYPE_SCHANNEL:
-                                       *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
+                                       *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
                                        break;
                                default:
                                        smb_panic("bad auth type");
                                        break;
                        }
 
-                       data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
-                                               RPC_HDR_AUTH_LEN - *p_auth_len;
+                       data_space = cli->max_xmit_frag
+                                       - DCERPC_REQUEST_LENGTH
+                                       - DCERPC_AUTH_TRAILER_LENGTH
+                                       - *p_auth_len;
 
                        data_len = MIN(data_space, data_left);
                        *p_ss_padding = 0;
-                       if (data_len % 8) {
-                               *p_ss_padding = 8 - (data_len % 8);
+                       if (data_len % CLIENT_NDR_PADDING_SIZE) {
+                               *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
                        }
-                       *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
-                                       data_len + *p_ss_padding +              /* data plus padding. */
-                                       RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
+                       *p_frag_len = DCERPC_REQUEST_LENGTH
+                                       + data_len + *p_ss_padding
+                                       + DCERPC_AUTH_TRAILER_LENGTH
+                                       + *p_auth_len;
                        return data_len;
 
                default:
@@ -2055,19 +2035,12 @@ struct rpc_api_pipe_req_state {
        struct rpc_pipe_client *cli;
        uint8_t op_num;
        uint32_t call_id;
-       prs_struct *req_data;
+       DATA_BLOB *req_data;
        uint32_t req_data_sent;
-       prs_struct outgoing_frag;
-       prs_struct reply_pdu;
+       DATA_BLOB rpc_out;
+       DATA_BLOB reply_pdu;
 };
 
-static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
-{
-       prs_mem_free(&s->outgoing_frag);
-       prs_mem_free(&s->reply_pdu);
-       return 0;
-}
-
 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
@@ -2077,7 +2050,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
                                         struct event_context *ev,
                                         struct rpc_pipe_client *cli,
                                         uint8_t op_num,
-                                        prs_struct *req_data)
+                                        DATA_BLOB *req_data)
 {
        struct tevent_req *req, *subreq;
        struct rpc_api_pipe_req_state *state;
@@ -2095,23 +2068,16 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
        state->req_data = req_data;
        state->req_data_sent = 0;
        state->call_id = get_rpc_call_id();
+       state->reply_pdu = data_blob_null;
+       state->rpc_out = data_blob_null;
 
-       if (cli->max_xmit_frag
-           < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
+       if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
+                                       + RPC_MAX_SIGN_SIZE) {
                /* Server is screwed up ! */
                status = NT_STATUS_INVALID_PARAMETER;
                goto post_status;
        }
 
-       prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
-
-       if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
-                     state, MARSHALL)) {
-               goto fail;
-       }
-
-       talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
-
        status = prepare_next_frag(state, &is_last_frag);
        if (!NT_STATUS_IS_OK(status)) {
                goto post_status;
@@ -2119,17 +2085,16 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
 
        if (is_last_frag) {
                subreq = rpc_api_pipe_send(state, ev, state->cli,
-                                          &state->outgoing_frag,
-                                          RPC_RESPONSE);
+                                          &state->rpc_out,
+                                          DCERPC_PKT_RESPONSE);
                if (subreq == NULL) {
                        goto fail;
                }
                tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
        } else {
-               subreq = rpc_write_send(
-                       state, ev, cli->transport,
-                       (uint8_t *)prs_data_p(&state->outgoing_frag),
-                       prs_offset(&state->outgoing_frag));
+               subreq = rpc_write_send(state, ev, cli->transport,
+                                       state->rpc_out.data,
+                                       state->rpc_out.length);
                if (subreq == NULL) {
                        goto fail;
                }
@@ -2149,8 +2114,6 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
                                  bool *is_last_frag)
 {
-       RPC_HDR hdr;
-       RPC_HDR_REQ hdr_req;
        uint32_t data_sent_thistime;
        uint16_t auth_len;
        uint16_t frag_len;
@@ -2159,51 +2122,57 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
        uint32_t data_left;
        char pad[8] = { 0, };
        NTSTATUS status;
+       union dcerpc_payload u;
 
-       data_left = prs_offset(state->req_data) - state->req_data_sent;
+       data_left = state->req_data->length - state->req_data_sent;
 
        data_sent_thistime = calculate_data_len_tosend(
                state->cli, data_left, &frag_len, &auth_len, &ss_padding);
 
        if (state->req_data_sent == 0) {
-               flags = RPC_FLG_FIRST;
+               flags = DCERPC_PFC_FLAG_FIRST;
        }
 
        if (data_sent_thistime == data_left) {
-               flags |= RPC_FLG_LAST;
-       }
-
-       if (!prs_set_offset(&state->outgoing_frag, 0)) {
-               return NT_STATUS_NO_MEMORY;
+               flags |= DCERPC_PFC_FLAG_LAST;
        }
 
-       /* Create and marshall the header and request header. */
-       init_rpc_hdr(&hdr, RPC_REQUEST, flags, state->call_id, frag_len,
-                    auth_len);
+       data_blob_free(&state->rpc_out);
 
-       if (!smb_io_rpc_hdr("hdr    ", &hdr, &state->outgoing_frag, 0)) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       ZERO_STRUCT(u.request);
 
-       /* Create the rpc request RPC_HDR_REQ */
-       init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
-                        state->op_num);
+       u.request.alloc_hint    = state->req_data->length;
+       u.request.context_id    = 0;
+       u.request.opnum         = state->op_num;
 
-       if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
-                               &state->outgoing_frag, 0)) {
-               return NT_STATUS_NO_MEMORY;
+       status = dcerpc_push_ncacn_packet(state,
+                                         DCERPC_PKT_REQUEST,
+                                         flags,
+                                         auth_len,
+                                         state->call_id,
+                                         &u,
+                                         &state->rpc_out);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
+       /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
+        * compute it right for requests */
+       dcerpc_set_frag_length(&state->rpc_out, frag_len);
+
        /* Copy in the data, plus any ss padding. */
-       if (!prs_append_some_prs_data(&state->outgoing_frag,
-                                     state->req_data, state->req_data_sent,
-                                     data_sent_thistime)) {
+       if (!data_blob_append(NULL, &state->rpc_out,
+                               state->req_data->data + state->req_data_sent,
+                               data_sent_thistime)) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       /* Copy the sign/seal padding data. */
-       if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
-               return NT_STATUS_NO_MEMORY;
+       if (ss_padding) {
+               /* Copy the sign/seal padding data. */
+               if (!data_blob_append(NULL, &state->rpc_out,
+                                       pad, ss_padding)) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        /* Generate any auth sign/seal and add the auth footer. */
@@ -2213,12 +2182,12 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
                break;
        case PIPE_AUTH_TYPE_NTLMSSP:
        case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-               status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
-                                                &state->outgoing_frag);
+               status = add_ntlmssp_auth_footer(state->cli, ss_padding,
+                                                &state->rpc_out);
                break;
        case PIPE_AUTH_TYPE_SCHANNEL:
-               status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
-                                                 &state->outgoing_frag);
+               status = add_schannel_auth_footer(state->cli, ss_padding,
+                                                 &state->rpc_out);
                break;
        default:
                status = NT_STATUS_INVALID_PARAMETER;
@@ -2226,7 +2195,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
        }
 
        state->req_data_sent += data_sent_thistime;
-       *is_last_frag = ((flags & RPC_FLG_LAST) != 0);
+       *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
 
        return status;
 }
@@ -2255,18 +2224,17 @@ static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
 
        if (is_last_frag) {
                subreq = rpc_api_pipe_send(state, state->ev, state->cli,
-                                          &state->outgoing_frag,
-                                          RPC_RESPONSE);
+                                          &state->rpc_out,
+                                          DCERPC_PKT_RESPONSE);
                if (tevent_req_nomem(subreq, req)) {
                        return;
                }
                tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
        } else {
-               subreq = rpc_write_send(
-                       state, state->ev,
-                       state->cli->transport,
-                       (uint8_t *)prs_data_p(&state->outgoing_frag),
-                       prs_offset(&state->outgoing_frag));
+               subreq = rpc_write_send(state, state->ev,
+                                       state->cli->transport,
+                                       state->rpc_out.data,
+                                       state->rpc_out.length);
                if (tevent_req_nomem(subreq, req)) {
                        return;
                }
@@ -2283,7 +2251,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq)
                req, struct rpc_api_pipe_req_state);
        NTSTATUS status;
 
-       status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
+       status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);
@@ -2293,7 +2261,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq)
 }
 
 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                              prs_struct *reply_pdu)
+                              DATA_BLOB *reply_pdu)
 {
        struct rpc_api_pipe_req_state *state = tevent_req_data(
                req, struct rpc_api_pipe_req_state);
@@ -2304,18 +2272,14 @@ NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                 * We always have to initialize to reply pdu, even if there is
                 * none. The rpccli_* caller routines expect this.
                 */
-               prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
+               *reply_pdu = data_blob_null;
                return status;
        }
 
-       *reply_pdu = state->reply_pdu;
-       reply_pdu->mem_ctx = mem_ctx;
-
-       /*
-        * Prevent state->req_pdu from being freed in
-        * rpc_api_pipe_req_state_destructor()
-        */
-       prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
+       /* return data to caller and assign it ownership of memory */
+       reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
+       reply_pdu->length = state->reply_pdu.length;
+       state->reply_pdu.length = 0;
 
        return NT_STATUS_OK;
 }
@@ -2371,23 +2335,31 @@ static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
  Check the rpc bind acknowledge response.
 ****************************************************************************/
 
-static bool check_bind_response(RPC_HDR_BA *hdr_ba,
+static bool check_bind_response(const struct dcerpc_bind_ack *r,
                                const struct ndr_syntax_id *transfer)
 {
-       if ( hdr_ba->addr.len == 0) {
+       struct dcerpc_ack_ctx ctx;
+
+       if (r->secondary_address_size == 0) {
                DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
        }
 
+       if (r->num_results < 1 || !r->ctx_list) {
+               return false;
+       }
+
+       ctx = r->ctx_list[0];
+
        /* check the transfer syntax */
-       if ((hdr_ba->transfer.if_version != transfer->if_version) ||
-            (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
+       if ((ctx.syntax.if_version != transfer->if_version) ||
+            (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
                DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
                return False;
        }
 
-       if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
+       if (r->num_results != 0x1 || ctx.result != 0) {
                DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
-                         hdr_ba->res.num_results, hdr_ba->res.reason));
+                         r->num_results, ctx.reason));
        }
 
        DEBUG(5,("check_bind_response: accepted!\n"));
@@ -2401,56 +2373,42 @@ static bool check_bind_response(RPC_HDR_BA *hdr_ba,
  the authentication handshake.
  ********************************************************************/
 
-static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
+static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
+                               struct rpc_pipe_client *cli,
                                uint32 rpc_call_id,
                                enum pipe_auth_type auth_type,
                                enum dcerpc_AuthLevel auth_level,
                                DATA_BLOB *pauth_blob,
-                               prs_struct *rpc_out)
+                               DATA_BLOB *rpc_out)
 {
-       RPC_HDR hdr;
-       RPC_HDR_AUTH hdr_auth;
-       uint32 pad = 0;
-
-       /* Create the request RPC_HDR */
-       init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
-                    RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
-                    pauth_blob->length );
-
-       /* Marshall it. */
-       if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /*
-               I'm puzzled about this - seems to violate the DCE RPC auth rules,
-               about padding - shouldn't this pad to length 8 ? JRA.
-       */
+       NTSTATUS status;
+       union dcerpc_payload u;
 
-       /* 4 bytes padding. */
-       if (!prs_uint32("pad", rpc_out, 0, &pad)) {
-               DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
+       u.auth3._pad = 0;
 
-       /* Create the request RPC_HDR_AUTHA */
-       init_rpc_hdr_auth(&hdr_auth,
+       status = dcerpc_push_dcerpc_auth(mem_ctx,
                        map_pipe_auth_type_to_rpc_auth_type(auth_type),
-                       auth_level, 0, 1);
-
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
-               return NT_STATUS_NO_MEMORY;
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        pauth_blob,
+                                        &u.auth3.auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       /*
-        * Append the auth data to the outgoing buffer.
-        */
-
-       if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
-               DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
-               return NT_STATUS_NO_MEMORY;
+       status = dcerpc_push_ncacn_packet(mem_ctx,
+                                         DCERPC_PKT_AUTH3,
+                                         DCERPC_PFC_FLAG_FIRST |
+                                         DCERPC_PFC_FLAG_LAST,
+                                         pauth_blob->length,
+                                         rpc_call_id,
+                                         &u,
+                                         rpc_out);
+       data_blob_free(&u.auth3.auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
+               return status;
        }
 
        return NT_STATUS_OK;
@@ -2461,40 +2419,37 @@ static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
  may contain a spnego auth blobl
  ********************************************************************/
 
-static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
+static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
+                                       uint32 rpc_call_id,
                                        const struct ndr_syntax_id *abstract,
                                        const struct ndr_syntax_id *transfer,
                                        enum dcerpc_AuthLevel auth_level,
                                        const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
-                                       prs_struct *rpc_out)
+                                       DATA_BLOB *rpc_out)
 {
-       RPC_HDR_AUTH hdr_auth;
-       prs_struct auth_info;
-       NTSTATUS ret = NT_STATUS_OK;
-
-       ZERO_STRUCT(hdr_auth);
-       if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
-               return NT_STATUS_NO_MEMORY;
-
-       /* We may change the pad length before marshalling. */
-       init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
+       DATA_BLOB auth_info;
+       NTSTATUS status;
 
-       if (pauth_blob->length) {
-               if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
-                       prs_mem_free(&auth_info);
-                       return NT_STATUS_NO_MEMORY;
-               }
+       status = dcerpc_push_dcerpc_auth(mem_ctx,
+                                        DCERPC_AUTH_TYPE_SPNEGO,
+                                        auth_level,
+                                        0, /* auth_pad_length */
+                                        1, /* auth_context_id */
+                                        pauth_blob,
+                                        &auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
-                                               rpc_out, 
-                                               rpc_call_id,
-                                               abstract,
-                                               transfer,
-                                               &hdr_auth,
-                                               &auth_info);
-       prs_mem_free(&auth_info);
-       return ret;
+       status = create_bind_or_alt_ctx_internal(mem_ctx,
+                                                DCERPC_PKT_ALTER,
+                                                rpc_call_id,
+                                                abstract,
+                                                transfer,
+                                                &auth_info,
+                                                rpc_out);
+       data_blob_free(&auth_info);
+       return status;
 }
 
 /****************************************************************************
@@ -2504,26 +2459,19 @@ static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
 struct rpc_pipe_bind_state {
        struct event_context *ev;
        struct rpc_pipe_client *cli;
-       prs_struct rpc_out;
+       DATA_BLOB rpc_out;
        uint32_t rpc_call_id;
 };
 
-static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
-{
-       prs_mem_free(&state->rpc_out);
-       return 0;
-}
-
 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
                                           struct rpc_pipe_bind_state *state,
-                                          struct rpc_hdr_info *phdr,
-                                          prs_struct *reply_pdu);
+                                          struct ncacn_packet *r);
 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
                                                    struct rpc_pipe_bind_state *state,
-                                                   struct rpc_hdr_info *phdr,
-                                                   prs_struct *reply_pdu);
+                                                   struct ncacn_packet *r,
+                                                   DATA_BLOB *reply_pdu);
 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
 
 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
@@ -2541,33 +2489,32 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
        }
 
        DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
-               rpccli_pipe_txt(debug_ctx(), cli),
+               rpccli_pipe_txt(talloc_tos(), cli),
                (unsigned int)auth->auth_type,
                (unsigned int)auth->auth_level ));
 
        state->ev = ev;
        state->cli = cli;
        state->rpc_call_id = get_rpc_call_id();
-
-       prs_init_empty(&state->rpc_out, state, MARSHALL);
-       talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
+       state->rpc_out = data_blob_null;
 
        cli->auth = talloc_move(cli, &auth);
 
        /* Marshall the outgoing data. */
-       status = create_rpc_bind_req(cli, &state->rpc_out,
+       status = create_rpc_bind_req(state, cli,
                                     state->rpc_call_id,
                                     &cli->abstract_syntax,
                                     &cli->transfer_syntax,
                                     cli->auth->auth_type,
-                                    cli->auth->auth_level);
+                                    cli->auth->auth_level,
+                                    &state->rpc_out);
 
        if (!NT_STATUS_IS_OK(status)) {
                goto post_status;
        }
 
        subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
-                                  RPC_BINDACK);
+                                  DCERPC_PKT_BIND_ACK);
        if (subreq == NULL) {
                goto fail;
        }
@@ -2588,46 +2535,28 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct rpc_pipe_bind_state *state = tevent_req_data(
                req, struct rpc_pipe_bind_state);
-       prs_struct reply_pdu;
-       struct rpc_hdr_info hdr;
-       struct rpc_hdr_ba_info hdr_ba;
+       DATA_BLOB reply_pdu;
+       struct ncacn_packet *pkt;
        NTSTATUS status;
 
-       status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
+       status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
-                         rpccli_pipe_txt(debug_ctx(), state->cli),
+                         rpccli_pipe_txt(talloc_tos(), state->cli),
                          nt_errstr(status)));
                tevent_req_nterror(req, status);
                return;
        }
 
-       /* Unmarshall the RPC header */
-       if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
-               DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
-               prs_mem_free(&reply_pdu);
-               tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-               return;
-       }
-
-       if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
-               DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
-                         "RPC_HDR_BA.\n"));
-               prs_mem_free(&reply_pdu);
-               tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-               return;
-       }
-
-       if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
+       if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
                DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
-               prs_mem_free(&reply_pdu);
                tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
                return;
        }
 
-       state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
-       state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
+       state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
+       state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
 
        /*
         * For authenticated binds we may need to do 3 or 4 leg binds.
@@ -2638,15 +2567,12 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
        case PIPE_AUTH_TYPE_NONE:
        case PIPE_AUTH_TYPE_SCHANNEL:
                /* Bind complete. */
-               prs_mem_free(&reply_pdu);
                tevent_req_done(req);
                break;
 
        case PIPE_AUTH_TYPE_NTLMSSP:
                /* Need to send AUTH3 packet - no reply. */
-               status = rpc_finish_auth3_bind_send(req, state, &hdr,
-                                                   &reply_pdu);
-               prs_mem_free(&reply_pdu);
+               status = rpc_finish_auth3_bind_send(req, state, pkt);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
                }
@@ -2654,9 +2580,8 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
 
        case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
                /* Need to send alter context request and reply. */
-               status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
+               status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
                                                             &reply_pdu);
-               prs_mem_free(&reply_pdu);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
                }
@@ -2668,45 +2593,38 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
        default:
                DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
                         (unsigned int)state->cli->auth->auth_type));
-               prs_mem_free(&reply_pdu);
                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
        }
 }
 
 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
                                           struct rpc_pipe_bind_state *state,
-                                          struct rpc_hdr_info *phdr,
-                                          prs_struct *reply_pdu)
+                                          struct ncacn_packet *r)
 {
-       DATA_BLOB server_response = data_blob_null;
        DATA_BLOB client_reply = data_blob_null;
-       struct rpc_hdr_auth_info hdr_auth;
+       struct dcerpc_auth auth;
        struct tevent_req *subreq;
        NTSTATUS status;
 
-       if ((phdr->auth_len == 0)
-           || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!prs_set_offset(
-                   reply_pdu,
-                   phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
+       if ((r->auth_length == 0)
+           || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
+                                       + r->auth_length)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
-               return NT_STATUS_INVALID_PARAMETER;
+       status = dcerpc_pull_dcerpc_auth(talloc_tos(),
+                                        &r->u.bind_ack.auth_info,
+                                        &auth, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
+                         nt_errstr(status)));
+               return status;
        }
 
        /* TODO - check auth_type/auth_level match. */
 
-       server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
-       prs_copy_data_out((char *)server_response.data, reply_pdu,
-                         phdr->auth_len);
-
        status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
-                               server_response, &client_reply);
+                               auth.credentials, &client_reply);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
@@ -2714,9 +2632,10 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
                return status;
        }
 
-       prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
+       data_blob_free(&state->rpc_out);
 
-       status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
+       status = create_rpc_bind_auth3(state,
+                                      state->cli, state->rpc_call_id,
                                       state->cli->auth->auth_type,
                                       state->cli->auth->auth_level,
                                       &client_reply, &state->rpc_out);
@@ -2727,8 +2646,7 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
        }
 
        subreq = rpc_write_send(state, state->ev, state->cli->transport,
-                               (uint8_t *)prs_data_p(&state->rpc_out),
-                               prs_offset(&state->rpc_out));
+                               state->rpc_out.data, state->rpc_out.length);
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -2753,51 +2671,49 @@ static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
 
 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
                                                    struct rpc_pipe_bind_state *state,
-                                                   struct rpc_hdr_info *phdr,
-                                                   prs_struct *reply_pdu)
+                                                   struct ncacn_packet *r,
+                                                   DATA_BLOB *reply_pdu)
 {
-       DATA_BLOB server_spnego_response = data_blob_null;
        DATA_BLOB server_ntlm_response = data_blob_null;
        DATA_BLOB client_reply = data_blob_null;
        DATA_BLOB tmp_blob = data_blob_null;
-       RPC_HDR_AUTH hdr_auth;
+       struct dcerpc_auth auth_info;
+       DATA_BLOB auth_blob;
        struct tevent_req *subreq;
        NTSTATUS status;
 
-       if ((phdr->auth_len == 0)
-           || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
+       if ((r->auth_length == 0)
+           || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
+                                       + r->auth_length)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Process the returned NTLMSSP blob first. */
-       if (!prs_set_offset(
-                   reply_pdu,
-                   phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
-               return NT_STATUS_INVALID_PARAMETER;
+       auth_blob = data_blob_const(reply_pdu->data
+                                       + r->frag_length
+                                       - DCERPC_AUTH_TRAILER_LENGTH
+                                       - r->auth_length,
+                                   DCERPC_AUTH_TRAILER_LENGTH
+                                       + r->auth_length);
+
+       status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
+               return status;
        }
 
-       server_spnego_response = data_blob(NULL, phdr->auth_len);
-       prs_copy_data_out((char *)server_spnego_response.data,
-                         reply_pdu, phdr->auth_len);
-
        /*
         * The server might give us back two challenges - tmp_blob is for the
         * second.
         */
-       if (!spnego_parse_challenge(server_spnego_response,
+       if (!spnego_parse_challenge(auth_info.credentials,
                                    &server_ntlm_response, &tmp_blob)) {
-               data_blob_free(&server_spnego_response);
                data_blob_free(&server_ntlm_response);
                data_blob_free(&tmp_blob);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* We're finished with the server spnego response and the tmp_blob. */
-       data_blob_free(&server_spnego_response);
        data_blob_free(&tmp_blob);
 
        status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
@@ -2820,9 +2736,10 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
        tmp_blob = data_blob_null;
 
        /* Now prepare the alter context pdu. */
-       prs_init_empty(&state->rpc_out, state, MARSHALL);
+       data_blob_free(&state->rpc_out);
 
-       status = create_rpc_alter_context(state->rpc_call_id,
+       status = create_rpc_alter_context(state,
+                                         state->rpc_call_id,
                                          &state->cli->abstract_syntax,
                                          &state->cli->transfer_syntax,
                                          state->cli->auth->auth_level,
@@ -2835,7 +2752,7 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
        }
 
        subreq = rpc_api_pipe_send(state, state->ev, state->cli,
-                                  &state->rpc_out, RPC_ALTCONTRESP);
+                                  &state->rpc_out, DCERPC_PKT_ALTER_RESP);
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -2849,58 +2766,39 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct rpc_pipe_bind_state *state = tevent_req_data(
                req, struct rpc_pipe_bind_state);
-       DATA_BLOB server_spnego_response = data_blob_null;
        DATA_BLOB tmp_blob = data_blob_null;
-       prs_struct reply_pdu;
-       struct rpc_hdr_info hdr;
-       struct rpc_hdr_auth_info hdr_auth;
+       struct ncacn_packet *pkt;
+       struct dcerpc_auth auth;
        NTSTATUS status;
 
-       status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
+       status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);
                return;
        }
 
-       /* Get the auth blob from the reply. */
-       if (!smb_io_rpc_hdr("rpc_hdr   ", &hdr, &reply_pdu, 0)) {
-               DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
-                         "unmarshall RPC_HDR.\n"));
-               tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-               return;
-       }
-
-       if (!prs_set_offset(
-                   &reply_pdu,
-                   hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
-               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
-       }
-
-       if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
-               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+       status = dcerpc_pull_dcerpc_auth(pkt,
+                                        &pkt->u.alter_resp.auth_info,
+                                        &auth, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
                return;
        }
 
-       server_spnego_response = data_blob(NULL, hdr.auth_len);
-       prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
-                         hdr.auth_len);
-
        /* Check we got a valid auth response. */
-       if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
+       if (!spnego_parse_auth_response(auth.credentials,
+                                       NT_STATUS_OK,
                                        OID_NTLMSSP, &tmp_blob)) {
-               data_blob_free(&server_spnego_response);
                data_blob_free(&tmp_blob);
                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
 
-       data_blob_free(&server_spnego_response);
        data_blob_free(&tmp_blob);
 
        DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
-                "%s.\n", rpccli_pipe_txt(debug_ctx(), state->cli)));
+                "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
        tevent_req_done(req);
 }
 
@@ -2940,15 +2838,40 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        return status;
 }
 
+#define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
+
 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
                                unsigned int timeout)
 {
-       struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
+       unsigned int old;
 
-       if (cli == NULL) {
-               return 0;
+       if (rpc_cli->transport == NULL) {
+               return RPCCLI_DEFAULT_TIMEOUT;
+       }
+
+       if (rpc_cli->transport->set_timeout == NULL) {
+               return RPCCLI_DEFAULT_TIMEOUT;
+       }
+
+       old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
+       if (old == 0) {
+               return RPCCLI_DEFAULT_TIMEOUT;
+       }
+
+       return old;
+}
+
+bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
+{
+       if (rpc_cli == NULL) {
+               return false;
+       }
+
+       if (rpc_cli->transport == NULL) {
+               return false;
        }
-       return cli_set_timeout(cli, timeout);
+
+       return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
 }
 
 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
@@ -2999,7 +2922,7 @@ static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
        return 0;
 }
 
-NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
+static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
                                  enum pipe_auth_type auth_type,
                                  enum dcerpc_AuthLevel auth_level,
                                  const char *domain,
@@ -3025,7 +2948,11 @@ NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
                goto fail;
        }
 
-       status = ntlmssp_client_start(&result->a_u.ntlmssp_state);
+       status = ntlmssp_client_start(NULL,
+                                     global_myname(),
+                                     lp_workgroup(),
+                                     lp_client_ntlmv2_auth(),
+                                     &result->a_u.ntlmssp_state);
        if (!NT_STATUS_IS_OK(status)) {
                goto fail;
        }
@@ -3070,7 +2997,7 @@ NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
 
 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
                                   enum dcerpc_AuthLevel auth_level,
-                                  const uint8_t sess_key[16],
+                                  struct netlogon_creds_CredentialState *creds,
                                   struct cli_pipe_auth_data **presult)
 {
        struct cli_pipe_auth_data *result;
@@ -3089,15 +3016,15 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
                goto fail;
        }
 
-       result->a_u.schannel_auth = talloc(result,
-                                          struct schannel_auth_struct);
+       result->a_u.schannel_auth = talloc(result, struct schannel_state);
        if (result->a_u.schannel_auth == NULL) {
                goto fail;
        }
 
-       memcpy(result->a_u.schannel_auth->sess_key, sess_key,
-              sizeof(result->a_u.schannel_auth->sess_key));
+       result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
        result->a_u.schannel_auth->seq_num = 0;
+       result->a_u.schannel_auth->initiator = true;
+       result->a_u.schannel_auth->creds = creds;
 
        *presult = result;
        return NT_STATUS_OK;
@@ -3115,7 +3042,7 @@ static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
 }
 #endif
 
-NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
+static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
                                   enum dcerpc_AuthLevel auth_level,
                                   const char *service_princ,
                                   const char *username,
@@ -3377,18 +3304,13 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
        NTSTATUS status;
        uint16_t port = 0;
 
-       *presult = NULL;
-
        status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
        if (!NT_STATUS_IS_OK(status)) {
-               goto done;
+               return status;
        }
 
-       status = rpc_pipe_open_tcp_port(mem_ctx, host, port,
+       return rpc_pipe_open_tcp_port(mem_ctx, host, port,
                                        abstract_syntax, presult);
-
-done:
-       return status;
 }
 
 /********************************************************************
@@ -3458,14 +3380,14 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
        return status;
 }
 
-static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p)
-{
+struct rpc_pipe_client_np_ref {
        struct cli_state *cli;
+       struct rpc_pipe_client *pipe;
+};
 
-       cli = rpc_pipe_np_smb_conn(p);
-       if (cli != NULL) {
-               DLIST_REMOVE(cli->pipe_list, p);
-       }
+static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
+{
+       DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
        return 0;
 }
 
@@ -3488,6 +3410,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
 {
        struct rpc_pipe_client *result;
        NTSTATUS status;
+       struct rpc_pipe_client_np_ref *np_ref;
 
        /* sanity check to protect against crashes */
 
@@ -3526,8 +3449,16 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
 
        result->transport->transport = NCACN_NP;
 
-       DLIST_ADD(cli->pipe_list, result);
-       talloc_set_destructor(result, rpc_pipe_client_np_destructor);
+       np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
+       if (np_ref == NULL) {
+               TALLOC_FREE(result);
+               return NT_STATUS_NO_MEMORY;
+       }
+       np_ref->cli = cli;
+       np_ref->pipe = result;
+
+       DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
+       talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
 
        *presult = result;
        return NT_STATUS_OK;
@@ -3669,7 +3600,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
                }
                DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
                            "%s failed with error %s\n",
-                           get_pipe_name_from_iface(interface),
+                           get_pipe_name_from_syntax(talloc_tos(), interface),
                            nt_errstr(status) ));
                TALLOC_FREE(result);
                return status;
@@ -3677,7 +3608,8 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
 
        DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
                  "%s and bound anonymously.\n",
-                 get_pipe_name_from_iface(interface), cli->desthost));
+                 get_pipe_name_from_syntax(talloc_tos(), interface),
+                 cli->desthost));
 
        *presult = result;
        return NT_STATUS_OK;
@@ -3735,8 +3667,8 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
 
        DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
                "machine %s and bound NTLMSSP as user %s\\%s.\n",
-                 get_pipe_name_from_iface(interface), cli->desthost, domain,
-                 username ));
+                 get_pipe_name_from_syntax(talloc_tos(), interface),
+                 cli->desthost, domain, username ));
 
        *presult = result;
        return NT_STATUS_OK;
@@ -3805,7 +3737,7 @@ static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon
                                                const char *domain,
                                                uint32 *pneg_flags)
 {
-       uint32 sec_chan_type = 0;
+       enum netr_SchannelType sec_chan_type = 0;
        unsigned char machine_pwd[16];
        const char *machine_account;
        NTSTATUS status;
@@ -3904,7 +3836,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
        }
 
        status = rpccli_schannel_bind_data(result, domain, auth_level,
-                                          (*pdc)->session_key, &auth);
+                                          *pdc, &auth);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
                          nt_errstr(status)));
@@ -3926,15 +3858,10 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
         * in - reference them in
         */
        result->dc = talloc_move(result, pdc);
-       if (result->dc == NULL) {
-               DEBUG(0, ("talloc reference failed\n"));
-               TALLOC_FREE(result);
-               return NT_STATUS_NO_MEMORY;
-       }
 
        DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
                  "for domain %s and bound using schannel.\n",
-                 get_pipe_name_from_iface(interface),
+                 get_pipe_name_from_syntax(talloc_tos(), interface),
                  cli->desthost, domain ));
 
        *presult = result;
@@ -4055,7 +3982,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
                *presult = result;
        }
 
-       return NT_STATUS_OK;
+       return status;
 }
 
 /****************************************************************************
@@ -4122,7 +4049,7 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
        switch (cli->auth->auth_type) {
                case PIPE_AUTH_TYPE_SCHANNEL:
                        *session_key = data_blob_talloc(mem_ctx,
-                               cli->auth->a_u.schannel_auth->sess_key, 16);
+                               cli->auth->a_u.schannel_auth->creds->session_key, 16);
                        break;
                case PIPE_AUTH_TYPE_NTLMSSP:
                case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: