diff options
author | Jeremy Allison <jra@samba.org> | 2013-11-07 21:40:55 -0800 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2013-12-05 10:18:10 +0100 |
commit | c406802cf767929c7016041da51fb512094a7f30 (patch) | |
tree | 9d8a0358b9245eab38145503a55bd8b9857c847d /source4 | |
parent | ca5d6f5eed28350a7d0a5179e2d4ca31d0069959 (diff) | |
download | samba-c406802cf767929c7016041da51fb512094a7f30.tar.gz |
CVE-2013-4408:s3:Ensure LookupNames replies arrays are range checked.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/util/clilsa.c | 6 | ||||
-rw-r--r-- | source4/libnet/groupinfo.c | 9 | ||||
-rw-r--r-- | source4/libnet/groupman.c | 10 | ||||
-rw-r--r-- | source4/libnet/libnet_join.c | 12 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.c | 5 | ||||
-rw-r--r-- | source4/libnet/libnet_passwd.c | 10 | ||||
-rw-r--r-- | source4/libnet/userinfo.c | 8 | ||||
-rw-r--r-- | source4/libnet/userman.c | 24 | ||||
-rw-r--r-- | source4/winbind/wb_async_helpers.c | 13 |
9 files changed, 68 insertions, 29 deletions
diff --git a/source4/libcli/util/clilsa.c b/source4/libcli/util/clilsa.c index cc0dae5984..0437352e75 100644 --- a/source4/libcli/util/clilsa.c +++ b/source4/libcli/util/clilsa.c @@ -335,7 +335,11 @@ NTSTATUS smblsa_lookup_name(struct smbcli_state *cli, } if (sids.count != 1) { talloc_free(mem_ctx2); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + if (domains->count != 1) { + talloc_free(mem_ctx2); + return NT_STATUS_INVALID_NETWORK_RESPONSE; } sid = domains->domains[0].sid; diff --git a/source4/libnet/groupinfo.c b/source4/libnet/groupinfo.c index 9060973e02..5c8b0f734c 100644 --- a/source4/libnet/groupinfo.c +++ b/source4/libnet/groupinfo.c @@ -88,11 +88,14 @@ static void continue_groupinfo_lookup(struct tevent_req *subreq) s->monitor_fn(&msg); } - /* have we actually got name resolved - we're looking for only one at the moment */ - if (s->lookup.out.rids->count == 0) { - composite_error(c, NT_STATUS_NO_SUCH_USER); + if (s->lookup.out.rids->count != s->lookup.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + if (s->lookup.out.types->count != s->lookup.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } diff --git a/source4/libnet/groupman.c b/source4/libnet/groupman.c index 9771ea5496..59a3f35d62 100644 --- a/source4/libnet/groupman.c +++ b/source4/libnet/groupman.c @@ -219,13 +219,13 @@ static void continue_groupdel_name_found(struct tevent_req *subreq) /* what to do when there's no group account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids->count) { - c->status = NT_STATUS_NO_SUCH_GROUP; + if (s->lookupname.out.rids->count != s->lookupname.in.num_names) { + c->status = NT_STATUS_INVALID_NETWORK_RESPONSE; composite_error(c, c->status); return; - - } else if (!s->lookupname.out.rids->count > 1) { - c->status = NT_STATUS_INVALID_ACCOUNT_NAME; + } + if (s->lookupname.out.types->count != s->lookupname.in.num_names) { + c->status = NT_STATUS_INVALID_NETWORK_RESPONSE; composite_error(c, c->status); return; } diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 09774038fb..8c1b57ddde 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -656,9 +656,17 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru "samr_LookupNames for [%s] returns %d RIDs", r->in.account_name, ln.out.rids->count); talloc_free(tmp_ctx); - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_INVALID_NETWORK_RESPONSE; } - + + if (ln.out.types->count != 1) { + r->out.error_string = talloc_asprintf(mem_ctx, + "samr_LookupNames for [%s] returns %d RID TYPEs", + r->in.account_name, ln.out.types->count); + talloc_free(tmp_ctx); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + /* prepare samr_OpenUser */ ZERO_STRUCTP(u_handle); ou.in.domain_handle = &d_handle; diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c index cf2d70c41d..77072b7ecc 100644 --- a/source4/libnet/libnet_lookup.c +++ b/source4/libnet/libnet_lookup.c @@ -365,6 +365,11 @@ static void continue_name_found(struct tevent_req *subreq) c->status = s->lookup.out.result; if (!composite_is_ok(c)) return; + if (s->lookup.out.sids->count != s->lookup.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + composite_done(c); } diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c index 861d746fd1..77176bc16c 100644 --- a/source4/libnet/libnet_passwd.c +++ b/source4/libnet/libnet_passwd.c @@ -627,10 +627,18 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * r->samr.out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] returns %d RIDs", r->samr.in.account_name, ln.out.rids->count); - status = NT_STATUS_INVALID_PARAMETER; + status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto disconnect; } + if (ln.out.types->count != 1) { + r->samr.out.error_string = talloc_asprintf(mem_ctx, + "samr_LookupNames for [%s] returns %d RID TYPEs", + r->samr.in.account_name, ln.out.types->count); + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + goto disconnect; + } + /* prepare samr_OpenUser */ ZERO_STRUCT(u_handle); ou.in.domain_handle = &d_handle; diff --git a/source4/libnet/userinfo.c b/source4/libnet/userinfo.c index 75c46e477d..9530f9efdb 100644 --- a/source4/libnet/userinfo.c +++ b/source4/libnet/userinfo.c @@ -90,8 +90,12 @@ static void continue_userinfo_lookup(struct tevent_req *subreq) /* have we actually got name resolved - we're looking for only one at the moment */ - if (s->lookup.out.rids->count == 0) { - composite_error(c, NT_STATUS_NO_SUCH_USER); + if (s->lookup.out.rids->count != s->lookup.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + if (s->lookup.out.types->count != s->lookup.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c index c1ee017990..a7301eab6c 100644 --- a/source4/libnet/userman.c +++ b/source4/libnet/userman.c @@ -237,14 +237,12 @@ static void continue_userdel_name_found(struct tevent_req *subreq) /* what to do when there's no user account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids->count) { - c->status = NT_STATUS_NO_SUCH_USER; - composite_error(c, c->status); + if (s->lookupname.out.rids->count != s->lookupname.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; - - } else if (!s->lookupname.out.rids->count > 1) { - c->status = NT_STATUS_INVALID_ACCOUNT_NAME; - composite_error(c, c->status); + } + if (s->lookupname.out.types->count != s->lookupname.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -513,14 +511,12 @@ static void continue_usermod_name_found(struct tevent_req *subreq) /* what to do when there's no user account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids->count) { - c->status = NT_STATUS_NO_SUCH_USER; - composite_error(c, c->status); + if (s->lookupname.out.rids->count != s->lookupname.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; - - } else if (!s->lookupname.out.rids->count > 1) { - c->status = NT_STATUS_INVALID_ACCOUNT_NAME; - composite_error(c, c->status); + } + if (s->lookupname.out.types->count != s->lookupname.in.num_names) { + composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index e3de2eb38e..2a05f12465 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -285,6 +285,12 @@ static void lsa_lookupnames_recv_sids(struct tevent_req *subreq) return; } + if (state->sids.count != state->num_names) { + composite_error(state->ctx, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + state->result = talloc_array(state, struct wb_sid_object *, state->num_names); if (composite_nomem(state->result, state->ctx)) return; @@ -303,9 +309,14 @@ static void lsa_lookupnames_recv_sids(struct tevent_req *subreq) continue; } + if (domains == NULL) { + composite_error(state->ctx, + NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } if (sid->sid_index >= domains->count) { composite_error(state->ctx, - NT_STATUS_INVALID_PARAMETER); + NT_STATUS_INVALID_NETWORK_RESPONSE); return; } |