[PATCH] drsuapi.idl: Manage all possible lengths of DsBindInfo
Samuel Cabrero
scabrero at zentyal.com
Fri Jul 4 09:08:45 MDT 2014
Hello,
we have reports about samba not able to join to domain and crashing with
the following exception:
'drsuapi.DsBindInfoFallBack' object has no attribute 'supported_extensions'
Digging into the problem it seems to be in the drsuapi IDL. The
DsBindInfo blob returned by the server is decoded in the IDL, based on
the blob length. For some reason, some servers are returning a 32 bytes
length blob, which is not decoded, so it falls into the default case and
python bindings crash.
Reviewing the documentation [MS-DRSR], it is possible the server not to
push the object GUID of the configuration NC, so I have added that case
and also the one to decode the blob returned by W2K12 R2 which is 52 bytes.
Cheers.
--
Samuel Cabrero - Developer
scabrero at zentyal.com
Zentyal - Active Exchange
www.zentyal.com
-------------- next part --------------
>From f272d62415eec04128c3820de33187fe241a9f75 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero at zentyal.com>
Date: Fri, 4 Jul 2014 12:45:59 +0200
Subject: [PATCH] idl:drsuapi: Manage all possible lengths of
drsuapi_DsBindInfo
Signed-off-by: Samuel Cabrero <scabrero at zentyal.com>
Reviewed-by: Kamen Mazdrashki <kamenim at samba.org>
---
librpc/idl/drsuapi.idl | 21 +++++++++++++++++++++
source3/libnet/libnet_dssync.c | 21 ++++++++++++++++++++-
source3/rpcclient/cmd_drsuapi.c | 4 ++++
source4/dsdb/repl/drepl_out_helpers.c | 27 ++++++++++++++++++++++++++-
source4/libnet/libnet_become_dc.c | 25 ++++++++++++++++++++++++-
source4/libnet/libnet_unbecome_dc.c | 25 ++++++++++++++++++++++++-
source4/torture/drs/rpc/dssync.c | 21 ++++++++++++++++++++-
source4/torture/drs/rpc/msds_intid.c | 21 ++++++++++++++++++++-
source4/torture/rpc/dsgetinfo.c | 21 ++++++++++++++++++++-
9 files changed, 179 insertions(+), 7 deletions(-)
diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl
index f1c6cd6..b78a865 100644
--- a/librpc/idl/drsuapi.idl
+++ b/librpc/idl/drsuapi.idl
@@ -129,6 +129,14 @@ interface drsuapi
uint32 repl_epoch;
} drsuapi_DsBindInfo28;
+ typedef [public] struct {
+ drsuapi_SupportedExtensions supported_extensions;
+ GUID site_guid;
+ uint32 pid;
+ uint32 repl_epoch;
+ drsuapi_SupportedExtensionsExt supported_extensions_ext;
+ } drsuapi_DsBindInfo32;
+
/* this is used by w2k8 */
typedef [public] struct {
drsuapi_SupportedExtensions supported_extensions;
@@ -139,6 +147,17 @@ interface drsuapi
GUID config_dn_guid;
} drsuapi_DsBindInfo48;
+ /* this is used by w2k12 R2 [MS-DRSR] Section 5.39 */
+ typedef [public] struct {
+ drsuapi_SupportedExtensions supported_extensions;
+ GUID site_guid;
+ uint32 pid;
+ uint32 repl_epoch;
+ drsuapi_SupportedExtensionsExt supported_extensions_ext;
+ GUID config_dn_guid;
+ drsuapi_SupportedExtensionsExt supported_capabilities_ext;
+ } drsuapi_DsBindInfo52;
+
typedef [public] struct {
[flag(NDR_REMAINING)] DATA_BLOB info;
} drsuapi_DsBindInfoFallBack;
@@ -146,7 +165,9 @@ interface drsuapi
typedef [nopull, nopush, noprint] [nodiscriminant] union {
[case(24)][subcontext(0), subcontext_size(24)] drsuapi_DsBindInfo24 info24;
[case(28)][subcontext(0), subcontext_size(28)] drsuapi_DsBindInfo28 info28;
+ [case(32)][subcontext(0), subcontext_size(32)] drsuapi_DsBindInfo32 info32;
[case(48)][subcontext(0), subcontext_size(48)] drsuapi_DsBindInfo48 info48;
+ [case(52)][subcontext(0), subcontext_size(52)] drsuapi_DsBindInfo52 info52;
/*
* The size for the defaut case is a bit arbitrary it in fact the value
* of the switch but we can't reference it.
diff --git a/source3/libnet/libnet_dssync.c b/source3/libnet/libnet_dssync.c
index a843106..94f0628 100644
--- a/source3/libnet/libnet_dssync.c
+++ b/source3/libnet/libnet_dssync.c
@@ -195,9 +195,19 @@ static NTSTATUS libnet_dssync_bind(TALLOC_CTX *mem_ctx,
ctx->remote_info28.repl_epoch = 0;
break;
}
- case 28:
+ case 28: {
ctx->remote_info28 = bind_info.info.info28;
break;
+ }
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &bind_info.info.info32;
+ ctx->remote_info28.site_guid = info32->site_guid;
+ ctx->remote_info28.supported_extensions = info32->supported_extensions;
+ ctx->remote_info28.pid = info32->pid;
+ ctx->remote_info28.repl_epoch = info32->repl_epoch;
+ break;
+ }
case 48: {
struct drsuapi_DsBindInfo48 *info48;
info48 = &bind_info.info.info48;
@@ -207,6 +217,15 @@ static NTSTATUS libnet_dssync_bind(TALLOC_CTX *mem_ctx,
ctx->remote_info28.repl_epoch = info48->repl_epoch;
break;
}
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &bind_info.info.info52;
+ ctx->remote_info28.site_guid = info52->site_guid;
+ ctx->remote_info28.supported_extensions = info52->supported_extensions;
+ ctx->remote_info28.pid = info52->pid;
+ ctx->remote_info28.repl_epoch = info52->repl_epoch;
+ break;
+ }
default:
DEBUG(1, ("Warning: invalid info length in bind info: %d\n",
bind_info.length));
diff --git a/source3/rpcclient/cmd_drsuapi.c b/source3/rpcclient/cmd_drsuapi.c
index 0c281cf..6a1fac7 100644
--- a/source3/rpcclient/cmd_drsuapi.c
+++ b/source3/rpcclient/cmd_drsuapi.c
@@ -420,8 +420,12 @@ static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli,
supported_extensions = bind_info.info.info24.supported_extensions;
} else if (bind_info.length == 28) {
supported_extensions = bind_info.info.info28.supported_extensions;
+ } else if (bind_info.length == 32) {
+ supported_extensions = bind_info.info.info32.supported_extensions;
} else if (bind_info.length == 48) {
supported_extensions = bind_info.info.info48.supported_extensions;
+ } else if (bind_info.length == 52) {
+ supported_extensions = bind_info.info.info52.supported_extensions;
}
if (!nc_dn) {
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 2339027..22d44f0 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -186,10 +186,35 @@ static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq)
info28->repl_epoch = info48->repl_epoch;
break;
}
- case 28:
+ case 28: {
*info28 = state->bind_r.out.bind_info->info.info28;
break;
}
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &state->bind_r.out.bind_info->info.info32;
+
+ info28->supported_extensions = info32->supported_extensions;
+ info28->site_guid = info32->site_guid;
+ info28->pid = info32->pid;
+ info28->repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &state->bind_r.out.bind_info->info.info52;
+
+ info28->supported_extensions = info52->supported_extensions;
+ info28->site_guid = info52->site_guid;
+ info28->pid = info52->pid;
+ info28->repl_epoch = info52->repl_epoch;
+ break;
+ }
+ default:
+ DEBUG(1, ("Warning: invalid info length in bind info: %d\n",
+ state->bind_r.out.bind_info->length));
+ break;
+ }
}
tevent_req_done(req);
diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c
index 6d00fcc..55ac48c 100644
--- a/source4/libnet/libnet_become_dc.c
+++ b/source4/libnet/libnet_become_dc.c
@@ -1712,10 +1712,33 @@ static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
drsuapi->remote_info28.repl_epoch = info48->repl_epoch;
break;
}
- case 28:
+ case 28: {
drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
break;
}
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &drsuapi->bind_r.out.bind_info->info.info32;
+ drsuapi->remote_info28.supported_extensions = info32->supported_extensions;
+ drsuapi->remote_info28.site_guid = info32->site_guid;
+ drsuapi->remote_info28.pid = info32->pid;
+ drsuapi->remote_info28.repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &drsuapi->bind_r.out.bind_info->info.info52;
+ drsuapi->remote_info28.supported_extensions = info52->supported_extensions;
+ drsuapi->remote_info28.site_guid = info52->site_guid;
+ drsuapi->remote_info28.pid = info52->pid;
+ drsuapi->remote_info28.repl_epoch = info52->repl_epoch;
+ break;
+ }
+ default:
+ DEBUG(1, ("Warning: invalid info length in bind info: %d\n",
+ drsuapi->bind_r.out.bind_info->length));
+ break;
+ }
}
return WERR_OK;
diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c
index f575eb1..2ff7b1c 100644
--- a/source4/libnet/libnet_unbecome_dc.c
+++ b/source4/libnet/libnet_unbecome_dc.c
@@ -649,10 +649,33 @@ static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq)
s->drsuapi.remote_info28.repl_epoch = info48->repl_epoch;
break;
}
- case 28:
+ case 28: {
s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28;
break;
}
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &s->drsuapi.bind_r.out.bind_info->info.info32;
+ s->drsuapi.remote_info28.supported_extensions = info32->supported_extensions;
+ s->drsuapi.remote_info28.site_guid = info32->site_guid;
+ s->drsuapi.remote_info28.pid = info32->pid;
+ s->drsuapi.remote_info28.repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &s->drsuapi.bind_r.out.bind_info->info.info52;
+ s->drsuapi.remote_info28.supported_extensions = info52->supported_extensions;
+ s->drsuapi.remote_info28.site_guid = info52->site_guid;
+ s->drsuapi.remote_info28.pid = info52->pid;
+ s->drsuapi.remote_info28.repl_epoch = info52->repl_epoch;
+ break;
+ }
+ default:
+ DEBUG(1, ("Warning: invalid info length in bind info: %d\n",
+ s->drsuapi.bind_r.out.bind_info->length));
+ break;
+ }
}
unbecomeDC_drsuapi_remove_ds_server_send(s);
diff --git a/source4/torture/drs/rpc/dssync.c b/source4/torture/drs/rpc/dssync.c
index 813f136..0f13ea5 100644
--- a/source4/torture/drs/rpc/dssync.c
+++ b/source4/torture/drs/rpc/dssync.c
@@ -246,9 +246,28 @@ static bool _test_DsBind(struct torture_context *tctx,
b->peer_bind_info28.repl_epoch = info48->repl_epoch;
break;
}
- case 28:
+ case 28: {
b->peer_bind_info28 = b->req.out.bind_info->info.info28;
break;
+ }
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &b->req.out.bind_info->info.info32;
+ b->peer_bind_info28.supported_extensions= info32->supported_extensions;
+ b->peer_bind_info28.site_guid = info32->site_guid;
+ b->peer_bind_info28.pid = info32->pid;
+ b->peer_bind_info28.repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &b->req.out.bind_info->info.info52;
+ b->peer_bind_info28.supported_extensions= info52->supported_extensions;
+ b->peer_bind_info28.site_guid = info52->site_guid;
+ b->peer_bind_info28.pid = info52->pid;
+ b->peer_bind_info28.repl_epoch = info52->repl_epoch;
+ break;
+ }
default:
printf("DsBind - warning: unknown BindInfo length: %u\n",
b->req.out.bind_info->length);
diff --git a/source4/torture/drs/rpc/msds_intid.c b/source4/torture/drs/rpc/msds_intid.c
index a02acd8..b93f70a 100644
--- a/source4/torture/drs/rpc/msds_intid.c
+++ b/source4/torture/drs/rpc/msds_intid.c
@@ -244,9 +244,28 @@ static bool _test_DsaBind(struct torture_context *tctx,
bi->srv_info48.repl_epoch = info28->repl_epoch;
break;
}
- case 48:
+ case 48: {
bi->srv_info48 = r.out.bind_info->info.info48;
break;
+ }
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &r.out.bind_info->info.info32;
+ bi->srv_info48.supported_extensions = info32->supported_extensions;
+ bi->srv_info48.site_guid = info32->site_guid;
+ bi->srv_info48.pid = info32->pid;
+ bi->srv_info48.repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &r.out.bind_info->info.info52;
+ bi->srv_info48.supported_extensions = info52->supported_extensions;
+ bi->srv_info48.site_guid = info52->site_guid;
+ bi->srv_info48.pid = info52->pid;
+ bi->srv_info48.repl_epoch = info52->repl_epoch;
+ break;
+ }
default:
torture_result(tctx, TORTURE_FAIL,
"DsBind: unknown BindInfo length: %u",
diff --git a/source4/torture/rpc/dsgetinfo.c b/source4/torture/rpc/dsgetinfo.c
index 7d6b01f..93c8b2d 100644
--- a/source4/torture/rpc/dsgetinfo.c
+++ b/source4/torture/rpc/dsgetinfo.c
@@ -204,9 +204,28 @@ static bool _test_DsBind(struct torture_context *tctx,
b->peer_bind_info28.repl_epoch = info48->repl_epoch;
break;
}
- case 28:
+ case 28: {
b->peer_bind_info28 = b->req.out.bind_info->info.info28;
break;
+ }
+ case 32: {
+ struct drsuapi_DsBindInfo32 *info32;
+ info32 = &b->req.out.bind_info->info.info32;
+ b->peer_bind_info28.supported_extensions= info32->supported_extensions;
+ b->peer_bind_info28.site_guid = info32->site_guid;
+ b->peer_bind_info28.pid = info32->pid;
+ b->peer_bind_info28.repl_epoch = info32->repl_epoch;
+ break;
+ }
+ case 52: {
+ struct drsuapi_DsBindInfo52 *info52;
+ info52 = &b->req.out.bind_info->info.info52;
+ b->peer_bind_info28.supported_extensions= info52->supported_extensions;
+ b->peer_bind_info28.site_guid = info52->site_guid;
+ b->peer_bind_info28.pid = info52->pid;
+ b->peer_bind_info28.repl_epoch = info52->repl_epoch;
+ break;
+ }
default:
printf("DsBind - warning: unknown BindInfo length: %u\n",
b->req.out.bind_info->length);
--
1.9.1
More information about the samba-technical
mailing list