diff options
author | Andrew Tridgell <tridge@samba.org> | 2010-02-14 11:56:28 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2010-02-14 18:44:21 +1100 |
commit | 259129e8f4bc8cacd1850eba3f6551134835d079 (patch) | |
tree | c260895bc44323820cee72a8eaf6a77433090d5d | |
parent | ccfa40fdc3eb785b71a4d2d59933a2fdc352fb24 (diff) | |
download | samba-259129e8f4bc8cacd1850eba3f6551134835d079.tar.gz samba-259129e8f4bc8cacd1850eba3f6551134835d079.tar.bz2 samba-259129e8f4bc8cacd1850eba3f6551134835d079.zip |
a4-dcerpc: another attempt at dcerpc auth padding
The last change broke net vampire against w2k8r2
-rw-r--r-- | librpc/gen_ndr/dcerpc.h | 3 | ||||
-rw-r--r-- | librpc/gen_ndr/ndr_dcerpc.c | 9 | ||||
-rw-r--r-- | librpc/idl/dcerpc.idl | 3 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 19 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 8 | ||||
-rw-r--r-- | source4/rpc_server/dcesrv_auth.c | 8 |
6 files changed, 35 insertions, 15 deletions
diff --git a/librpc/gen_ndr/dcerpc.h b/librpc/gen_ndr/dcerpc.h index 375a4e900d..f05541c407 100644 --- a/librpc/gen_ndr/dcerpc.h +++ b/librpc/gen_ndr/dcerpc.h @@ -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] */; diff --git a/librpc/gen_ndr/ndr_dcerpc.c b/librpc/gen_ndr/ndr_dcerpc.c index 0884d8e505..dca445a872 100644 --- a/librpc/gen_ndr/ndr_dcerpc.c +++ b/librpc/gen_ndr/ndr_dcerpc.c @@ -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--; } diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl index ccf5e5de68..adc1f4ebb5 100644 --- a/librpc/idl/dcerpc.idl +++ b/librpc/idl/dcerpc.idl @@ -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; diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index e7b181c50b..ccafe070ab 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -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)) { diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 1985cb9e18..f41236148a 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -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); diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index d56dd12ac5..4d708e4dff 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -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; |