mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
a4-dcerpc: another attempt at dcerpc auth padding
The last change broke net vampire against w2k8r2
This commit is contained in:
parent
ccfa40fdc3
commit
259129e8f4
@ -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] */;
|
||||
|
||||
|
@ -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--;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user