The branch, master has been updated via c49c48afe09 ldb:utf8: ldb_ascii_toupper() avoids real toupper() via dca6b2d2552 ldb:attrib_handlers: use ldb_ascii_toupper() in first loop via 078ecf486a6 ldb:pytests: test for Turkic i-dots in ldb_comparison_fold via a75c98ad688 ldb:attrib_handlers: make ldb_comparison_Boolean more consistent via 7280c8e53f4 ldb-samba:ldif_handlers: dn_link_comparison: sort invalid DNs via 341b8fb60e2 ldb-samba:ldif_handlers: dn_link_comparison leaks less via 70356592563 ldb-samba:ldif_handlers: dn_link_comparison correctly sorts deleted objects via 11d5a809325 ldb-samba:ldif_handlers: dn_link_comparison semi-sorts invalid DNs via db963b1674e ldb-samba:ldif_handlers: dn_link_comparison semi-sorts deleted objects via 2d3b917d0a0 ldb-samba:ldif_handlers: extended_dn_read_Sid(): free on failure via 42f2d96f82a ldb-samba:ldif_handlers: ldif_read_objectSid(): free a thing on failure via 6722e80d1b3 ldb-samba: ldif-handlers: make ldif_comparison_objectSid() accurate via 4af670384a1 s4:dsdb: fix spelling in comment via a9eaf8a3abe ldb: comment for ldb_dn_compare_base via 6229feab74a s4:rpcsrv:samr: improve a comment in compare_msgRid via 7be535315a5 s4:rpcsrv:dnsserver: make dns_name_compare transitive with NULLs via 31c322874b8 s3:libsmb:nmblib: use NUMERIC_CMP in status_compare via 7ba6fcb9365 lib/socket: rearrange iface_comp() to use NUMERIC_CMP via acaa1323d03 gensec: sort_gensec uses NUMERIC_CMP via 75682e397b9 s3:rpc:wkssvc_nt: dom_user_cmp uses NUMERIC_CMP via 8317a617364 dsdb:schema: use NUMERIC_CMP in place of uint32_cmp via 386216d4a15 s3:mod:vfs_vxfs: use NUMERIC_CMP in vxfs_ace_cmp via 8b2605a5d9c s3:mod:posixacl_xattr: use NUMERIC_CMP in posixacl_xattr_entry_compare via 9b73235d495 s3:brlock: use NUMERIC_CMP in #ifdef-zeroed lock_compare via 5fe488d515a ldb:dn: make ldb_dn_compare() self-consistent via 531f31df993 ldb:sort: generalise both-NULL check to equality check via d4e69734c65 ldb:sort: check that elements have values via d785c1991c9 ldb:mod:sort: rearrange NULL checks from 20ce68f1594 tests/krb5: Test retrieving a denied gMSA password over an unsealed connection
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c49c48afe09a1a78989628bbffd49dd3efc154dd Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat Apr 20 09:57:15 2024 +1200 ldb:utf8: ldb_ascii_toupper() avoids real toupper() If a non-lowercase ASCII character has an uppercase counterpart in some locale, toupper() will convert it to an int codepoint. Probably that codepoint is too big to fit in our char return type, so we would truncate it to 8 bit. So it becomes an arbitrary mapping. It would also behave strangely with a byte with the top bit set, say 0xE2. If char is unsigned on this system, that is 'â', which uppercases to 'Â', with the codepoint 0xC2. That seems fine in isolation, but remember this is ldb_utf8.c, and that byte was not a codepoint but a piece of a long utf-8 encoding. In the more likely case where char is signed, toupper() is being passed a negative number, the result of which is undefined. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Apr 23 02:37:25 UTC 2024 on atb-devel-224 commit dca6b2d25529288eaf7b31baf37ca4f6de4f4b9d Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 13:46:28 2024 +1200 ldb:attrib_handlers: use ldb_ascii_toupper() in first loop In a dotless-I locale, we might meet an 'i' before we meet a byte with the high bit set, in which case we still want the ldb casefold comparison. Many ldb operations will do some case-folding before getting here, so hitting this might be quite rare even in those locales. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15637 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 078ecf486a62dc3aaa2842ada96456ac9870dad7 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Apr 17 11:42:30 2024 +1200 ldb:pytests: test for Turkic i-dots in ldb_comparison_fold In tr_TR and some other locales where the letter 'i' uppercases to 'İ', which is not ideal for LDB as we need certain strings like 'guid' to casefold in the ASCII way. In fixing https://bugzilla.samba.org/show_bug.cgi?id=15248) we solved this problem in many cases, but for unindexed searches where the 'i' is not the last character in the string. This test shows that. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15637 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a75c98ad688415aec8afc617a759ba90cfd9f23b Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Apr 10 10:54:41 2024 +1200 ldb:attrib_handlers: make ldb_comparison_Boolean more consistent This isn't supposed to be used for sorting, but it is hard to say it won't be, so we might as well make it sort properly. Following long-standing behaviour, we try to sort "FALSE" > "TRUE", by length, then switch to using strncasecmp(). strncasecmp would sort the other way, so we swap the operands. This is to make e.g. "TRUE\0" sort the same as "TRUE". BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7280c8e53f463108fe3de443ce63572dde689a30 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 18:08:54 2024 +1200 ldb-samba:ldif_handlers: dn_link_comparison: sort invalid DNs If both DNs are invalid, we can say they are equal. This means invalid or NULL DNs will sort to the end of the array, before deleted DNs: [ valid DNs, sorted | invalid/NULL DNs | deleted DNs, sorted ] BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 341b8fb60e291ad598fafd7a09a75e9b249de07f Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:59:50 2024 +1200 ldb-samba:ldif_handlers: dn_link_comparison leaks less dn1 and dn2 can be invalid but still occupying memory. (ldb_dn_validate(dn2) does contain a NULL check, but a lot more besides). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 70356592563bf758dbe509413445b77bb0d7da14 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:53:03 2024 +1200 ldb-samba:ldif_handlers: dn_link_comparison correctly sorts deleted objects This changes the behaviour of the DN syntax .comparison_fn when being used in a search, if the search key is a deleted DN. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 11d5a809325369b48d14023adf109e418bb1c7af Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:26:03 2024 +1200 ldb-samba:ldif_handlers: dn_link_comparison semi-sorts invalid DNs these tend to go to the end of the sorted array. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit db963b1674ede357d4edba578e0e0372dcb2f287 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:25:02 2024 +1200 ldb-samba:ldif_handlers: dn_link_comparison semi-sorts deleted objects We were always returning -1 for a deleted object, which works for an equality test, but not a relative comparison. This sorts deleted DNs toward the end of the list -- except when both DNs are deleted. What should happen there is yet to be determined. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 2d3b917d0a078279853bb3926b7dc3584fe53627 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:17:23 2024 +1200 ldb-samba:ldif_handlers: extended_dn_read_Sid(): free on failure Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 42f2d96f82a8156abb004c68d343c8b769ebea4b Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 16:15:39 2024 +1200 ldb-samba:ldif_handlers: ldif_read_objectSid(): free a thing on failure Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6722e80d1b3a252a1ed714be4a35185cd99971e3 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Apr 10 10:54:31 2024 +1200 ldb-samba: ldif-handlers: make ldif_comparison_objectSid() accurate This function compares blobs that might be SID strings or might be SID structures. Until now, if they were both (seemingly) strings, they were compared as strings, otherwise if either was a string it was converted to a structure blob, then the blobs were compared. This had two big problems: 1. There is variety in the way a SID can be stringified. For example, "s-1-02-3" means the same SID as "S-1-2-3", but those wouldn't compare equal. 2. SID comparison was crazily non-transitive. Consider the three values a = "S-1-2-3-4-5", b = "S-1-9-1", c = SID("S-1-11-1"), where c is a struct and the others are string. then we had, a < b, because the 5th character '2' < '9'. a > c, because when converted to a structure, the number of sub-auths is the first varying byte. a has 3, c has 0. b < c, because after the sub-auth count comes the id_auth value (big-endian, which doesn't matter in this case). That made the function unreliable for sorting, AND for simple equality tests. Also it leaked. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 4af670384a10a8571bc24ff2d7933160ee7adc62 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Apr 10 16:49:07 2024 +1200 s4:dsdb: fix spelling in comment Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a9eaf8a3abe66e1a5ff31fa405442f9a09f1dbc5 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Apr 10 16:48:39 2024 +1200 ldb: comment for ldb_dn_compare_base Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6229feab74a734190c302ee9b1cc36960669743d Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Mon Apr 8 22:55:50 2024 +1200 s4:rpcsrv:samr: improve a comment in compare_msgRid BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7be535315a5eed5d5b7eaea025ecf9f55e772e8e Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Mon Apr 8 22:54:49 2024 +1200 s4:rpcsrv:dnsserver: make dns_name_compare transitive with NULLs Returning 0 on `(name1 == NULL || name2 == NULL)` made NULL equal to everything, which confuses a sort (consider {A, B, NULL} where A > B, but A == NULL == B). The only caller is dnsserver_enumerate_records() which fails if it finds a NULL in the sorted list. We make the happen more quickly by sorting NULLs to the front. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 31c322874b8b65518cec945e05a42fd014e6390b Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Mon Apr 8 17:08:03 2024 +1200 s3:libsmb:nmblib: use NUMERIC_CMP in status_compare BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7ba6fcb93656e5e88e1d5bcd6002747aa64f0a3a Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Mon Apr 8 17:06:57 2024 +1200 lib/socket: rearrange iface_comp() to use NUMERIC_CMP We rearrange rather than just replacing the subtraction, because that would call ntohl() more than necessary, and I think the flow is a bit clearer this way. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit acaa1323d0337ae9339dfff9f856ea54725a86ac Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:54:02 2024 +1200 gensec: sort_gensec uses NUMERIC_CMP BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 75682e397b9cf22d04a5d80252554c6b2e376793 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:47:12 2024 +1200 s3:rpc:wkssvc_nt: dom_user_cmp uses NUMERIC_CMP usr->login_time is time_t, which is often bigger than int. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8317a6173646d425dc99e08bbf3d6086b0086bc5 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:36:06 2024 +1200 dsdb:schema: use NUMERIC_CMP in place of uint32_cmp uint32_cmp (introduced in 0c362597c0f933b3612bb17328c0a13b73d72e43 "fixed the sorting of schema attributes") was doing what NUMERIC_CMP does, but it was adding an extra function call. This results in less code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 386216d4a158d8bafb0879a0a753da096a939b93 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:17:22 2024 +1200 s3:mod:vfs_vxfs: use NUMERIC_CMP in vxfs_ace_cmp BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8b2605a5d9cc14f9e6ddf2db704cdca2f523d74e Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:12:56 2024 +1200 s3:mod:posixacl_xattr: use NUMERIC_CMP in posixacl_xattr_entry_compare The first subtraction was between uint16_t, so is safe with 32 bit int, but the second compared uint32_t, so was not safe. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9b73235d4957a487fbb3214fdfda6461a2cf0b21 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:07:20 2024 +1200 s3:brlock: use NUMERIC_CMP in #ifdef-zeroed lock_compare BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5fe488d515a8bb719bdeafb8b64d8479732b5ac8 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 15:04:43 2024 +1200 ldb:dn: make ldb_dn_compare() self-consistent We were returning -1 in all these cases: ldb_dn_compare(dn, NULL); ldb_dn_compare(NULL, dn); ldb_dn_compare(NULL, NULL); which would give strange results in sort, where this is often used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 531f31df99341b2cb1afc42538022451ca771983 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 14:58:48 2024 +1200 ldb:sort: generalise both-NULL check to equality check BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d4e69734c65ade0bbb398447012513a7f27e98bd Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 14:55:27 2024 +1200 ldb:sort: check that elements have values We assume no values is unlikely, since we have been dereferencing ->values[0] forever, with no known reports of trouble. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d785c1991c922150bab38c36cef3a799448ac304 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 7 14:54:34 2024 +1200 ldb:mod:sort: rearrange NULL checks There are further changes coming here. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/gensec/gensec_start.c | 2 +- lib/ldb-samba/ldif_handlers.c | 96 ++++++++++++++++++++----------- lib/ldb/common/attrib_handlers.c | 32 +++++++++-- lib/ldb/common/ldb_dn.c | 22 ++++++- lib/ldb/common/ldb_utf8.c | 12 +++- lib/ldb/modules/sort.c | 19 +++++- lib/ldb/tests/python/api.py | 16 ++++++ lib/socket/interfaces.c | 22 +++---- source3/libsmb/nmblib.c | 6 +- source3/locking/brlock.c | 7 +-- source3/modules/posixacl_xattr.c | 6 +- source3/modules/vfs_vxfs.c | 6 +- source3/rpc_server/wkssvc/srv_wkssvc_nt.c | 2 +- source4/dsdb/common/dsdb_dn.c | 2 +- source4/dsdb/schema/schema_set.c | 14 ++--- source4/rpc_server/dnsserver/dnsdata.c | 16 +++++- source4/rpc_server/samr/dcesrv_samr.c | 5 +- 17 files changed, 202 insertions(+), 83 deletions(-) Changeset truncated at 500 lines: diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 072188a6752..bcf98bd5968 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -1103,7 +1103,7 @@ _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void) } static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) { - return (*gs2)->priority - (*gs1)->priority; + return NUMERIC_CMP((*gs2)->priority, (*gs1)->priority); } int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value) diff --git a/lib/ldb-samba/ldif_handlers.c b/lib/ldb-samba/ldif_handlers.c index c30fd6358c8..f77f86fdcc0 100644 --- a/lib/ldb-samba/ldif_handlers.c +++ b/lib/ldb-samba/ldif_handlers.c @@ -110,6 +110,7 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx, ndr_err = ndr_push_struct_into_fixed_blob(out, &sid, (ndr_push_flags_fn_t)ndr_push_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(out->data); return -1; } } @@ -150,36 +151,47 @@ bool ldif_comparision_objectSid_isString(const struct ldb_val *v) /* compare two objectSids + + If the SIDs seem to be strings, they are converted to binary form. */ static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { - if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) { - return ldb_comparison_binary(ldb, mem_ctx, v1, v2); - } else if (ldif_comparision_objectSid_isString(v1) - && !ldif_comparision_objectSid_isString(v2)) { - struct ldb_val v; - int ret; - if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) { - /* Perhaps not a string after all */ - return ldb_comparison_binary(ldb, mem_ctx, v1, v2); + bool v1_is_string = ldif_comparision_objectSid_isString(v1); + bool v2_is_string = ldif_comparision_objectSid_isString(v2); + struct ldb_val parsed_1 = {}; + struct ldb_val parsed_2 = {}; + int ret; + /* + * If the ldb_vals look like SID strings (i.e. start with "S-" + * or "s-"), we try to parse them as such. If that fails, we + * assume they are binary SIDs, even though that's not really + * possible -- the first two bytes of a struct dom_sid are the + * version (1), and the number of sub-auths (<= 15), neither + * of which are close to 'S' or '-'. + */ + if (v1_is_string) { + int r = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1); + if (r == 0) { + v1 = &parsed_1; } - ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2); - talloc_free(v.data); - return ret; - } else if (!ldif_comparision_objectSid_isString(v1) - && ldif_comparision_objectSid_isString(v2)) { - struct ldb_val v; - int ret; - if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) { - /* Perhaps not a string after all */ - return ldb_comparison_binary(ldb, mem_ctx, v1, v2); + } + if (v2_is_string) { + int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2); + if (r == 0) { + v2 = &parsed_2; } - ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v); - talloc_free(v.data); - return ret; } - return ldb_comparison_binary(ldb, mem_ctx, v1, v2); + + ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2); + + if (v1_is_string) { + TALLOC_FREE(parsed_1.data); + } + if (v2_is_string) { + TALLOC_FREE(parsed_2.data); + } + return ret; } /* @@ -223,6 +235,7 @@ static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx, ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(out->data); return -1; } return 0; @@ -1148,22 +1161,41 @@ static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx, struct ldb_dn *dn1 = NULL, *dn2 = NULL; int ret; + /* + * In a sort context, Deleted DNs get shifted to the end. + * They never match in an equality + */ if (dsdb_dn_is_deleted_val(v1)) { - /* If the DN is deleted, then we can't search for it */ - return -1; - } - - if (dsdb_dn_is_deleted_val(v2)) { - /* If the DN is deleted, then we can't search for it */ + if (! dsdb_dn_is_deleted_val(v2)) { + return 1; + } + /* + * They are both deleted! + * + * The soundest thing to do at this point is carry on + * and compare the DNs normally. This matches the + * behaviour of samba_dn_extended_match() below. + */ + } else if (dsdb_dn_is_deleted_val(v2)) { return -1; } dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1); - if ( ! ldb_dn_validate(dn1)) return -1; - dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2); + + if ( ! ldb_dn_validate(dn1)) { + TALLOC_FREE(dn1); + if ( ! ldb_dn_validate(dn2)) { + TALLOC_FREE(dn2); + return 0; + } + TALLOC_FREE(dn2); + return 1; + } + if ( ! ldb_dn_validate(dn2)) { - talloc_free(dn1); + TALLOC_FREE(dn1); + TALLOC_FREE(dn2); return -1; } diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c index baccf193f88..6ae12c88eec 100644 --- a/lib/ldb/common/attrib_handlers.c +++ b/lib/ldb/common/attrib_handlers.c @@ -281,15 +281,36 @@ static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx, } /* - compare two Booleans -*/ + * compare two Booleans. + * + * According to RFC4517 4.2.2, "the booleanMatch rule is an equality matching + * rule", meaning it isn't used for ordering. + * + * However, it seems conceivable that Samba could be coerced into sorting on a + * field with Boolean syntax, so we might as well have consistent behaviour in + * that case. + * + * The most probably values are {"FALSE", 5} and {"TRUE", 4}. To save time we + * compare first by length, which makes FALSE > TRUE. This is somewhat + * contrary to convention, but is how Samba has worked forever. + * + * If somehow we are comparing incompletely normalised values where the length + * is the same (for example {"false", 5} and {"TRUE\0", 5}), the length is the + * same, and we fall back to a strncasecmp. In this case, since "FALSE" is + * alphabetically lower, we swap the order, so that "TRUE\0" again comes + * before "FALSE". + * + * ldb_canonicalise_Boolean (just above) gives us a clue as to what we might + * expect to cope with by way of invalid values. + */ static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { if (v1->length != v2->length) { - return NUMERIC_CMP(v1->length, v2->length); + return NUMERIC_CMP(v2->length, v1->length); } - return strncasecmp((char *)v1->data, (char *)v2->data, v1->length); + /* reversed, see long comment above */ + return strncasecmp((char *)v2->data, (char *)v1->data, v1->length); } @@ -330,8 +351,9 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, * never appear in multibyte sequences */ if (((unsigned char)s1[0]) & 0x80) goto utf8str; if (((unsigned char)s2[0]) & 0x80) goto utf8str; - if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) + if (ldb_ascii_toupper(*s1) != ldb_ascii_toupper(*s2)) { break; + } if (*s1 == ' ') { while (n1 > 1 && s1[0] == s1[1]) { s1++; n1--; } while (n2 > 1 && s2[0] == s2[1]) { s2++; n2--; } diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 7325a000f0a..d2517089da5 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -1038,7 +1038,11 @@ char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) /* Determine if dn is below base, in the ldap tree. Used for * evaluating a subtree search. - * 0 if they match, otherwise non-zero + * + * 0 if they match, otherwise non-zero. + * + * This is not for use in a qsort()-like function, as the comparison + * is not symmetric. */ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn) @@ -1132,8 +1136,22 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1) { unsigned int i; int ret; + /* + * If used in sort, we shift NULL and invalid DNs to the end. + * + * If ldb_dn_casefold_internal() fails, that goes to the end too, so + * we end up with: + * + * | normal DNs, sorted | casefold failed DNs | invalid DNs | NULLs | + */ - if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) { + if (dn0 == dn1 || (dn0->invalid && dn1->invalid)) { + return 0; + } + if (dn0 == NULL || dn0->invalid) { + return 1; + } + if (dn1 == NULL || dn1->invalid) { return -1; } diff --git a/lib/ldb/common/ldb_utf8.c b/lib/ldb/common/ldb_utf8.c index f45b72dde50..178bdd86de1 100644 --- a/lib/ldb/common/ldb_utf8.c +++ b/lib/ldb/common/ldb_utf8.c @@ -136,5 +136,15 @@ int ldb_attr_dn(const char *attr) } _PRIVATE_ char ldb_ascii_toupper(char c) { - return ('a' <= c && c <= 'z') ? c ^ 0x20 : toupper(c); + /* + * We are aiming for a 1970s C-locale toupper(), when all letters + * were 7-bit and behaved with true American spirit. + * + * For example, we don't want the "i" in "<guid=" to be upper-cased to + * "İ" as would happen in some locales, or we won't be able to parse + * that properly. This is unfortunate for cases where we are dealing + * with real text; a search for the name "Ali" would need to be + * written "Alİ" to match. + */ + return ('a' <= c && c <= 'z') ? c ^ 0x20 : c; } diff --git a/lib/ldb/modules/sort.c b/lib/ldb/modules/sort.c index cb6f8df440f..72c60fc894a 100644 --- a/lib/ldb/modules/sort.c +++ b/lib/ldb/modules/sort.c @@ -121,15 +121,28 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo el1 = ldb_msg_find_element(*msg1, ac->attributeName); el2 = ldb_msg_find_element(*msg2, ac->attributeName); - if (!el1 && el2) { + /* + * NULL and empty elements sort at the end (regardless of ac->reverse flag). + * NULL elements come after empty ones. + */ + if (el1 == el2) { + return 0; + } + if (el1 == NULL) { return 1; } - if (el1 && !el2) { + if (el2 == NULL) { return -1; } - if (!el1 && !el2) { + if (unlikely(el1->num_values == 0 && el2->num_values == 0)) { return 0; } + if (unlikely(el1->num_values == 0)) { + return 1; + } + if (unlikely(el2->num_values == 0)) { + return -1; + } if (ac->reverse) return ac->a->syntax->comparison_fn(ldb, ac, &el2->values[0], &el1->values[0]); diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 88dfa8c3b71..0fc31e3fe09 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -1341,6 +1341,22 @@ class SearchTests(LdbBaseTest): expression="(ou=unique)") self.assertEqual(len(res11), 1) + def test_subtree_uni123_elsewhere(self): + """Testing a search, where the search term contains a (normal ASCII) + dotted-i, that will be upper-cased to 'İ', U+0130, LATIN + CAPITAL LETTER I WITH DOT ABOVE in certain locales including + tr_TR in which this test is sometimes run. + + The search term should fail because the ou does not exist, but + we used to get it wrong in unindexed searches which stopped + comparing at the i, ignoring the rest of the string, which is + not the same as the existing ou ('123' != 'que'). + """ + res11 = self.l.search(base="DC=EXAMPLE,DC=NET", + scope=ldb.SCOPE_SUBTREE, + expression="(ou=uni123)") + self.assertEqual(len(res11), 0) + def test_subtree_unique_elsewhere3(self): """Testing a search""" diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c index 4908b0f55e2..2426ce2b52a 100644 --- a/lib/socket/interfaces.c +++ b/lib/socket/interfaces.c @@ -386,18 +386,18 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) if (((struct sockaddr *)&i1->ip)->sa_family == AF_INET) { struct sockaddr_in *s1 = (struct sockaddr_in *)&i1->ip; struct sockaddr_in *s2 = (struct sockaddr_in *)&i2->ip; - - r = ntohl(s1->sin_addr.s_addr) - - ntohl(s2->sin_addr.s_addr); - if (r) { - return r; + uint32_t a1 = ntohl(s1->sin_addr.s_addr); + uint32_t a2 = ntohl(s2->sin_addr.s_addr); + r = NUMERIC_CMP(a1, a2); + if (r == 0) { + /* compare netmasks as a tiebreaker */ + s1 = (struct sockaddr_in *)&i1->netmask; + s2 = (struct sockaddr_in *)&i2->netmask; + a1 = ntohl(s1->sin_addr.s_addr); + a2 = ntohl(s2->sin_addr.s_addr); + r = NUMERIC_CMP(a1, a2); } - - s1 = (struct sockaddr_in *)&i1->netmask; - s2 = (struct sockaddr_in *)&i2->netmask; - - return ntohl(s1->sin_addr.s_addr) - - ntohl(s2->sin_addr.s_addr); + return r; } return 0; } diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 232b8003973..2297dd9ded9 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -1235,8 +1235,10 @@ static unsigned char sort_ip[4]; static int name_query_comp(unsigned char *p1, unsigned char *p2) { - return matching_len_bits(p2+2, sort_ip, 4) - - matching_len_bits(p1+2, sort_ip, 4); + int a = matching_len_bits(p1+2, sort_ip, 4); + int b = matching_len_bits(p2+2, sort_ip, 4); + /* reverse sort -- p2 derived value comes first */ + return NUMERIC_CMP(b, a); } /**************************************************************************** diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 905da049c58..328a9bfba3d 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -408,12 +408,9 @@ static int lock_compare(const struct lock_struct *lck1, const struct lock_struct *lck2) { if (lck1->start != lck2->start) { - return (lck1->start - lck2->start); + return NUMERIC_CMP(lck1->start, lck2->start); } - if (lck2->size != lck1->size) { - return ((int)lck1->size - (int)lck2->size); - } - return 0; + return NUMERIC_CMP(lck1->size, lck2->size); } #endif diff --git a/source3/modules/posixacl_xattr.c b/source3/modules/posixacl_xattr.c index 365cdc79973..5d0516cf754 100644 --- a/source3/modules/posixacl_xattr.c +++ b/source3/modules/posixacl_xattr.c @@ -226,14 +226,14 @@ static int posixacl_xattr_entry_compare(const void *left, const void *right) tag_left = SVAL(left, 0); tag_right = SVAL(right, 0); - ret = (tag_left - tag_right); - if (!ret) { + ret = NUMERIC_CMP(tag_left, tag_right); + if (ret == 0) { /* ID is the third element in the entry, after two short integers (tag and perm), i.e at offset 4. */ id_left = IVAL(left, 4); id_right = IVAL(right, 4); - ret = id_left - id_right; + ret = NUMERIC_CMP(id_left, id_right); } return ret; diff --git a/source3/modules/vfs_vxfs.c b/source3/modules/vfs_vxfs.c index aae2ca17337..ecc53d015f2 100644 --- a/source3/modules/vfs_vxfs.c +++ b/source3/modules/vfs_vxfs.c @@ -111,13 +111,13 @@ static int vxfs_ace_cmp(const void *ace1, const void *ace2) type_a1 = SVAL(ace1, 0); type_a2 = SVAL(ace2, 0); - ret = (type_a1 - type_a2); - if (!ret) { + ret = NUMERIC_CMP(type_a1, type_a2); + if (ret == 0) { /* Compare ID under type */ /* skip perm thus take offset as 4*/ id_a1 = IVAL(ace1, 4); id_a2 = IVAL(ace2, 4); - ret = id_a1 - id_a2; + ret = NUMERIC_CMP(id_a1, id_a2); } return ret; diff --git a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c index 0724dd00af5..ed16278b9fc 100644 --- a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c +++ b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c @@ -50,7 +50,7 @@ static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2) /* Called from qsort to compare two domain users in a dom_usr_t array * for sorting by login time. Return >0 if usr1 login time was later * than usr2 login time, <0 if it was earlier */ - return (usr1->login_time - usr2->login_time); + return NUMERIC_CMP(usr1->login_time, usr2->login_time); } /******************************************************************* diff --git a/source4/dsdb/common/dsdb_dn.c b/source4/dsdb/common/dsdb_dn.c index 63a8628d6d3..9886d831488 100644 --- a/source4/dsdb/common/dsdb_dn.c +++ b/source4/dsdb/common/dsdb_dn.c @@ -530,7 +530,7 @@ static struct ldb_dn *drs_ObjectIdentifier_to_dn(TALLOC_CTX *mem_ctx, * not valid or able to parse as a DN. * * Finally, we must return the DN as found in the DB, as otherwise a - * subsequence ldb_dn_compare(dn, nc_root) will fail (as this is based + * subsequent ldb_dn_compare(dn, nc_root) will fail (as this is based * on the string components). */ int drs_ObjectIdentifier_to_dn_and_nc_root(TALLOC_CTX *mem_ctx, diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 398091c6375..8b90e7f7b7f 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -478,19 +478,13 @@ static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_ TALLOC_FREE(frame); } -static int uint32_cmp(uint32_t c1, uint32_t c2) -{ - if (c1 == c2) return 0; - return c1 > c2 ? 1 : -1; -} - static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2) { return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName); } static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2) { - return uint32_cmp((*c1)->governsID_id, (*c2)->governsID_id); + return NUMERIC_CMP((*c1)->governsID_id, (*c2)->governsID_id); } static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2) { -- Samba Shared Repository