a4-dcerpc: another attempt at dcerpc auth padding
authorAndrew Tridgell <tridge@samba.org>
Sun, 14 Feb 2010 00:56:28 +0000 (11:56 +1100)
committerAndrew Tridgell <tridge@samba.org>
Sun, 14 Feb 2010 07:44:21 +0000 (18:44 +1100)
The last change broke net vampire against w2k8r2

librpc/gen_ndr/dcerpc.h
librpc/gen_ndr/ndr_dcerpc.c
librpc/idl/dcerpc.idl
source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc_util.c
source4/rpc_server/dcesrv_auth.c

index 375a4e900d6945060b5ffc72b1dd41237b97cc66..f05541c40721c99c3da7c2ac4ae21fc55509b4bc 100644 (file)
@@ -180,14 +180,17 @@ struct dcerpc_auth {
 }/* [public] */;
 
 struct dcerpc_auth3 {
+       uint32_t _pad;/* [value(0)] */
        DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
 }/* [public] */;
 
 struct dcerpc_orphaned {
+       uint32_t _pad;/* [value(0)] */
        DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
 }/* [public] */;
 
 struct dcerpc_co_cancel {
+       uint32_t _pad;/* [value(0)] */
        DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
 }/* [public] */;
 
index 0884d8e505c96ef909f0772423a560c259aa2a8f..dca445a872a2a2cddc7d2bfe0cb6e3ba12cf6249 100644 (file)
@@ -866,6 +866,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_dcerpc_auth3(struct ndr_push *ndr, int ndr_f
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -883,6 +884,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_auth3(struct ndr_pull *ndr, int ndr_f
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -900,6 +902,7 @@ _PUBLIC_ void ndr_print_dcerpc_auth3(struct ndr_print *ndr, const char *name, co
 {
        ndr_print_struct(ndr, name, "dcerpc_auth3");
        ndr->depth++;
+       ndr_print_uint32(ndr, "_pad", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?0:r->_pad);
        ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
        ndr->depth--;
 }
@@ -908,6 +911,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_dcerpc_orphaned(struct ndr_push *ndr, int nd
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -925,6 +929,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_orphaned(struct ndr_pull *ndr, int nd
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -942,6 +947,7 @@ _PUBLIC_ void ndr_print_dcerpc_orphaned(struct ndr_print *ndr, const char *name,
 {
        ndr_print_struct(ndr, name, "dcerpc_orphaned");
        ndr->depth++;
+       ndr_print_uint32(ndr, "_pad", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?0:r->_pad);
        ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
        ndr->depth--;
 }
@@ -950,6 +956,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_dcerpc_co_cancel(struct ndr_push *ndr, int n
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -967,6 +974,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_co_cancel(struct ndr_pull *ndr, int n
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
                {
                        uint32_t _flags_save_DATA_BLOB = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
@@ -984,6 +992,7 @@ _PUBLIC_ void ndr_print_dcerpc_co_cancel(struct ndr_print *ndr, const char *name
 {
        ndr_print_struct(ndr, name, "dcerpc_co_cancel");
        ndr->depth++;
+       ndr_print_uint32(ndr, "_pad", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?0:r->_pad);
        ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
        ndr->depth--;
 }
index ccf5e5de681c7f40d6860eedbe1c66b66040522a..adc1f4ebb59c8972779ee4136cc37be1c7370d07 100644 (file)
@@ -155,14 +155,17 @@ interface dcerpc
        const uint8 DCERPC_AUTH_TRAILER_LENGTH = 8;
 
        typedef [public] struct {
+               [value(0)]            uint32    _pad;
                [flag(NDR_REMAINING)] DATA_BLOB auth_info;
        } dcerpc_auth3;
 
        typedef [public] struct {
+               [value(0)]            uint32    _pad;
                [flag(NDR_REMAINING)] DATA_BLOB auth_info;
        } dcerpc_orphaned;
 
        typedef [public] struct {
+               [value(0)]            uint32    _pad;
                [flag(NDR_REMAINING)] DATA_BLOB auth_info;
        } dcerpc_co_cancel;
 
index e7b181c50bc09fa4e9ca5235104de4273be4eafb..ccafe070abbf0b30b42831f437b72e513c5ad0b7 100644 (file)
@@ -318,6 +318,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        size_t payload_length;
        enum ndr_err_code ndr_err;
        size_t hdr_size = DCERPC_REQUEST_LENGTH;
+       uint32_t offset;
 
        /* non-signed packets are simpler */
        if (sig_size == 0) {
@@ -362,17 +363,15 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return ndr_map_error2ntstatus(ndr_err);
        }
-       status = NT_STATUS_OK;
 
        /* pad to 16 byte multiple in the payload portion of the
           packet. This matches what w2k3 does */
-       c->security_state.auth_info->auth_pad_length = 
-               (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
-       ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
+       offset = ndr->offset;
+       ndr_err = ndr_push_align(ndr, 16);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return ndr_map_error2ntstatus(ndr_err);
        }
-       status = NT_STATUS_OK;
+       c->security_state.auth_info->auth_pad_length = ndr->offset - offset;
 
        payload_length = pkt->u.request.stub_and_verifier.length + 
                c->security_state.auth_info->auth_pad_length;
@@ -385,7 +384,6 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return ndr_map_error2ntstatus(ndr_err);
        }
-       status = NT_STATUS_OK;
 
        /* extract the whole packet as a blob */
        *blob = ndr_push_blob(ndr);
@@ -433,12 +431,17 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        }
 
        if (creds2.length != sig_size) {
-               DEBUG(0,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
+               /* this means the sig_size estimate for the signature
+                  was incorrect. We have to correct the packet
+                  sizes. That means we could go over the max fragment
+                  length */
+               DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
                        (unsigned) creds2.length,
                        (unsigned) sig_size,
                        (unsigned) c->security_state.auth_info->auth_pad_length,
                        (unsigned) pkt->u.request.stub_and_verifier.length));
-               return NT_STATUS_INTERNAL_ERROR;
+               dcerpc_set_frag_length(blob, blob->length + creds2.length);
+               dcerpc_set_auth_length(blob, creds2.length);
        }
 
        if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
index 1985cb9e18bd0127866ce90a515e0a7cc2df2769..f41236148a255da48cfa08ed3183db6be59b449c 100644 (file)
@@ -52,8 +52,8 @@ const struct ndr_interface_call *dcerpc_iface_find_call(const struct ndr_interfa
 */
 NTSTATUS ncacn_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
                         struct smb_iconv_convenience *iconv_convenience,
-                         struct ncacn_packet *pkt,
-                         struct dcerpc_auth *auth_info)
+                        struct ncacn_packet *pkt,
+                        struct dcerpc_auth *auth_info)
 {
        struct ndr_push *ndr;
        enum ndr_err_code ndr_err;
@@ -83,10 +83,12 @@ NTSTATUS ncacn_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
        }
 
        if (auth_info) {
-               ndr_err = ndr_push_zero(ndr, auth_info->auth_pad_length);
+               uint32_t offset = ndr->offset;
+               ndr_err = ndr_push_align(ndr, 16);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        return ndr_map_error2ntstatus(ndr_err);
                }
+               auth_info->auth_pad_length = ndr->offset - offset;
                ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        return ndr_map_error2ntstatus(ndr_err);
index d56dd12ac5063a1eb1485dd30f59b51d5ec9aec4..4d708e4dffd06fd633d333d0ae687f4d50bc9347 100644 (file)
@@ -378,7 +378,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
        NTSTATUS status;
        enum ndr_err_code ndr_err;
        struct ndr_push *ndr;
-       uint32_t payload_length;
+       uint32_t payload_length, offset;
        DATA_BLOB creds2;
 
        /* non-signed packets are simple */
@@ -423,12 +423,12 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
        }
 
        /* pad to 16 byte multiple, match win2k3 */
-       dce_conn->auth_state.auth_info->auth_pad_length =
-               (16 - (pkt->u.response.stub_and_verifier.length & 15)) & 15;
-       ndr_err = ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);
+       offset = ndr->offset;
+       ndr_err = ndr_push_align(ndr, 16);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return false;
        }
+       dce_conn->auth_state.auth_info->auth_pad_length = ndr->offset - offset;
 
        payload_length = pkt->u.response.stub_and_verifier.length +
                dce_conn->auth_state.auth_info->auth_pad_length;