The branch, master has been updated via 9844ac289be ldb-samba: ldif_read_objectSid avoids VLA via bf4af1a28a3 ldb-samba: ldif_read_objectSid() short-circuits without 'S' via 6c0bdf37187 lib/fuzzing: add fuzz_stable_sort_r_unstable via 59cbaa91348 ldb: note a transitivity problem in ldb_comparison_fold via e2051eebd49 ldb:attrib_handlers: reduce non-transitive behaviour in ldb_comparison_fold via f81b7c7eb20 ldb:attrib_handlers: use NUMERIC_CMP in ldb_comparison_fold via 3e899ef5bfa ldb-samba: remove unused ldif_comparision_objectSid_isString() via 8c702735641 ldb-samba: simplify extended_dn_read_SID() via c6c7cb8d4ba ldb-samba: simplify ldif_canonicalise_objectSid() via be5fd9a3a1b ldb-samba: simplify ldif_comparison_objectSid() via d801ed8b111 pytest: sid_strings: Samba DN object refuses sub-auth overflow via edf9b282ba6 pytest: sid_strings: adjust to match Windows 2016 via 473502d1701 pytest: sid_strings: Windows does allow lowercase s-1-... SIDs via fb724c61107 pytest: sid_strings: use more reliable well known SID via ae4f095586e ldb-samba: ldif_write_schemaInfo() uses correct size via 13af2cb0217 lib:util: codepoint_cmpi: be transitive and case-insensitive via 310d59c7cc3 lib:util:tests: more tests for codepoint_cmpi via 827b0c39ed0 s4:dsdb:mod: repl_md: message sort uses NUMERIC_CMP() via c5c29f59fa6 s4:rpc_srv:getncchanges: USN sort uses qsort() instead of ldb_qsort() via 65df8ce05c1 s4:rpc_srv:getncchanges: 4.5 anc emulation uses qsort(), not ldb_qsort() via 5335f122fb5 s4:dsdb:mod: repl_md: make message_sort transitive via 7f995ab887a ldb:tools: ldbsearch doesn't need ldb_qsort() via b37186cf917 s4:dsdb:util_trusts: simplify the NULL case in dns_cmp via 91b802941c1 s4:dsdb:util_trusts: describe dns_cmp return values via 8f080c0295d ldb:tests: add a test for dotted i uppercase via af7654331fb ldb: avoid NULL deref in ldb_db_compare from d58a72c572f .gitlab-ci: Remove tags no longer provided by gitlab.com
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 9844ac289be3430fd3f72c5e57fa00e012c5d417 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat May 4 13:40:35 2024 +1200 ldb-samba: ldif_read_objectSid avoids VLA I don't think this variable length array is any trouble, but people complain about them (e.g. https://nullprogram.com/blog/2019/10/27/) because they make things more complex at run-time, and this is a somewhat performance sensitive path. DOM_SID_STR_BUFLEN + 1 is 191 -- if that stack allocation is going to cause trouble, then so was the VLA <= that. 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): Wed May 8 00:26:42 UTC 2024 on atb-devel-224 commit bf4af1a28a3580223fcc3a861c7fdd1b43f234d1 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat May 4 13:32:39 2024 +1200 ldb-samba: ldif_read_objectSid() short-circuits without 'S' This avoids a memcpy, and level 3 debug verbosity from dom_sid_parse_endp(). In other places we have something like `|| in->data[1] != '-'`, but that is not useful here -- the value is either a string SID, or a binary SID that starts with '\1', or some awful value that we *do* want to get messages about. This replaces the work of ldif_comparision_objectSid_isString(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6c0bdf371878eb1a3a1c3b1663379a89bd0ec2c0 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed May 1 17:16:38 2024 +1200 lib/fuzzing: add fuzz_stable_sort_r_unstable This should find out how well stable_sort copes with an unstable non-transitive comparison function. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 59cbaa91348857c51854ee5e6bc8f78cdcde4e56 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Tue Apr 30 12:41:25 2024 +1200 ldb: note a transitivity problem in ldb_comparison_fold Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e2051eebd492a419f840280336eb242d0b4a26ac Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 26 15:58:44 2024 +1200 ldb:attrib_handlers: reduce non-transitive behaviour in ldb_comparison_fold If two strings are invalid UTF-8, the string is first compared with memcmp(), which compares as unsigned char. If the strings are of different lengths and one is a substring of the other, the memcmp() returns 0 and a second comparison is made which assumes the next character in the shorter string is '\0' -- but this comparison was done using SIGNED chars (on most systems). That leads to non-transitive comparisons. Consider the strings {"a\xff", "a", "ab\xff"} under that system. "a\xff" < "a", because (char)0xff == -1. "ab\xff" > "a", because 'b' == 98. "ab\xff" < "a\xff", because memcmp("ab\xff", "a\xff", 2) avoiding the signed char tiebreaker. (Before c49c48afe09a1a78989628bbffd49dd3efc154dd, the final character might br arbitrarily cast into another character -- in latin-1, for example, the 0xff here would have been seen as 'ÿ', which would be uppercased to 'Ÿ', which is U+0178, which would be truncated to '\x78', a positive char. On the other hand e.g. 0xfe, 'þ', would have mapped to 0xde, 'Þ', remaining negative). 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 f81b7c7eb206a447d799a25cc2da26304dc7567a Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 11 13:21:25 2024 +1200 ldb:attrib_handlers: use NUMERIC_CMP in ldb_comparison_fold 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 3e899ef5bfa67a12e8eb18cbebc06367f37a8376 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 18 01:49:11 2024 +1200 ldb-samba: remove unused ldif_comparision_objectSid_isString() This is unused because it does things badly, by just guessing and not allowing valid sids that start with "s-". All the places that used to use it were calling ldif_read_objectSid() or similar which correctly check for string SIDs by actually trying to parse them. That begins with looking for the "S-"/"s-", so this shortcut is not saving any real work. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8c702735641aaad58c317843c547249c6bd1c716 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 18 01:44:03 2024 +1200 ldb-samba: simplify extended_dn_read_SID() This will allow the reading of SIDs that start with "s-", which Windows allows, and we allow elsewhere. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c6c7cb8d4ba0e115034f4f0f7ff4a9943e54d914 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 18 01:42:27 2024 +1200 ldb-samba: simplify ldif_canonicalise_objectSid() ldif_comparision_objectSid_isString() is doing not useful or accurate, and ldif_read_objectSid() checks properly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit be5fd9a3a1b91dbd41e2bd0b025e3d3ffb598463 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 18 00:38:17 2024 +1200 ldb-samba: simplify ldif_comparison_objectSid() The ldif_comparision_objectSid_isString() call is both wrong (disallowing "s-") and redundant, because ldif_read_objectSid() calls dom_sid_parse(), which does the check properly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d801ed8b11125527b0b8193c8d0e430b5fb2c3a7 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri May 3 11:29:31 2024 +1200 pytest: sid_strings: Samba DN object refuses sub-auth overflow We were mistakenly asserting something that did not happen with Windows, because Samba already won't parse the DN string. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit edf9b282ba6e3fc089ab2d8a4db122b300b95fe4 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri May 3 11:24:02 2024 +1200 pytest: sid_strings: adjust to match Windows 2016 9 hex-digit subauths like '0xABCDef123' will not fit in 32 bits, so should be rejected on parsing. In other situations, such as defaultSecurityDescriptor, overflowing SID subauths on Windows will saturate to 0xffffffff, resulting in a valid but probably meaningless SID. It is possible that in previous testing we saw that here, but it is more likely I got confused. In any case, now I see them being rejected, and that is good. The saturating defaultSecurityDescriptor case is tested in SidStringBehavioursThatWindowsAllows. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 473502d170190b6bfe8da29708d347b16e0a2f7f Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri May 3 11:19:16 2024 +1200 pytest: sid_strings: Windows does allow lowercase s-1-... SIDs And so should we. Right now, these tests won't pass against Windows because they rely on ldb pre-parsing of the SIDs, so they fail before Windows gets to see them. Running them against Windows looks something like this, BTW: SAMBA_SID_STRINGS_SKIP_LOCAL=1 \ SMB_CONF_PATH=st/ad_dc/etc/smb.conf \ PYTHONPATH=bin/default/python \ DC_SERVER=192.168.122.126 \ DC_USERNAME=Administrator DC_PASSWORD='xxx' \ python3 python/samba/tests/sid_strings.py When things are right, the only failing tests should be from the SidStringBehavioursThatSambaPrefers suite. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fb724c61107b76d32b500802f960aa8e049ccbd8 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu May 2 14:24:18 2024 +1200 pytest: sid_strings: use more reliable well known SID It seems as if the well-known SID S-1-5-32-579 (DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS) is not always present -- specifically, it was not there on the Windows machine used to develop these tests, but it is there on the one I am now using. S-1-5-32-545 (DOMAIN_ALIAS_RID_USERS) is surely going to exist, so we use that instead. That changes some of the assertions, making some NO_SUCH_OBJECTs into successes. For these tests we are only interested in the parsing of the SIDs, not their meaning, so it's OK to change it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ae4f095586e50d765f404cd85e9aacf21e84892d Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat Apr 13 22:39:49 2024 +1200 ldb-samba: ldif_write_schemaInfo() uses correct size repsFromToBlob is much bigger, so this only meant we briefly allocated more than we needed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 13af2cb02171c0f10133813746e2f938ae2e304d Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat Apr 13 17:53:24 2024 +1200 lib:util: codepoint_cmpi: be transitive and case-insensitive the less/greater conparisons were not case-sensitive, which made the whole function non-transitive. I think codepoint_cmpi() is currently only used for equality tests, so nothing will change. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 310d59c7cc38f82e2906c4a5c80db140ad2a1548 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sat Apr 13 17:07:20 2024 +1200 lib:util:tests: more tests for codepoint_cmpi is codepoint_cmpi as case-insensitive as it claims when it comes to inequalities? (no, it is not!). Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 827b0c39ed0497407bfcfc5683735a165b1b0f0a Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 20:28:04 2024 +1200 s4:dsdb:mod: repl_md: message sort uses NUMERIC_CMP() No change at all in the result, just saving lines and branches. 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 c5c29f59fa6baa1564a7fde55e2b0639a6a8a39c Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 18:33:47 2024 +1200 s4:rpc_srv:getncchanges: USN sort uses qsort() instead of ldb_qsort() Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 65df8ce05c1d1bb9dd93592269ef966446cc5746 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 18:32:42 2024 +1200 s4:rpc_srv:getncchanges: 4.5 anc emulation uses qsort(), not ldb_qsort() Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5335f122fb551231a02a58f88f6a0aa23b5e02cb Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 18:11:47 2024 +1200 s4:dsdb:mod: repl_md: make message_sort transitive Before we had (with a TODO of regret): if (!a1 || !a2) { return strcasecmp(e1->name, e2->name); } so, given {name:"A", id 2}, {name:"B", NO id}, {name:"C", id 1}, A < B by name B < C by name A > C by id Now the sort order is always A > C > B. This sort could have caused mysterious crashes in repl_meta_data if the schema is out of sync. 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 7f995ab887a487df2213cbb7e9f79a09346e86ba Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 18:11:12 2024 +1200 ldb:tools: ldbsearch doesn't need ldb_qsort() When the opaque context blob is not used, we might as well use a real qsort(). Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b37186cf917ba9416b9d255e2d00d24cb8d12347 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed May 1 16:26:14 2024 +1200 s4:dsdb:util_trusts: simplify the NULL case in dns_cmp In this comparison function a NULL string is treated as the ancestor of all names, but you need to look hard to see that. By pulling the logic for NULLs to the front, hopefully we have to look less hard. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 91b802941c17f81398b08a66b5bedfa1127db070 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 12 21:28:31 2024 +1200 s4:dsdb:util_trusts: describe dns_cmp return values Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8f080c0295d07b526740882469e1577a44c79060 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Tue Apr 16 23:31:45 2024 +1200 ldb:tests: add a test for dotted i uppercase This didn't fail in the tr_TR locale before recent changes for https://bugzilla.samba.org/show_bug.cgi?id=15637, because this is a different casefold codepath. But it could fail if that other path goes wrong, so we might as well have the test. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit af7654331fb6a2d9cc41cf5bdffa74c81ff4ffee Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 26 15:24:47 2024 +1200 ldb: avoid NULL deref in ldb_db_compare This also sorts NULLs after invalid DNs, which matches the comment above. CID 1596622. 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: ...able_sort_r.c => fuzz_stable_sort_r_unstable.c} | 53 +++++++++++---- lib/fuzzing/wscript_build | 5 ++ lib/ldb-samba/ldif_handlers.c | 77 +++++++++------------- lib/ldb/common/attrib_handlers.c | 47 +++++++++++-- lib/ldb/common/ldb_dn.c | 16 ++++- lib/ldb/tests/python/api.py | 4 ++ lib/ldb/tools/ldbsearch.c | 5 +- lib/util/charset/codepoints.c | 18 +---- lib/util/charset/tests/charset.c | 11 +++- python/samba/tests/sid_strings.py | 26 ++++---- selftest/knownfail.d/sid-strings | 6 +- source4/dsdb/common/util_trusts.c | 32 +++++++-- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 17 +++-- source4/rpc_server/drsuapi/getncchanges.c | 20 +++--- 14 files changed, 207 insertions(+), 130 deletions(-) copy lib/fuzzing/{fuzz_stable_sort_r.c => fuzz_stable_sort_r_unstable.c} (61%) Changeset truncated at 500 lines: diff --git a/lib/fuzzing/fuzz_stable_sort_r.c b/lib/fuzzing/fuzz_stable_sort_r_unstable.c similarity index 61% copy from lib/fuzzing/fuzz_stable_sort_r.c copy to lib/fuzzing/fuzz_stable_sort_r_unstable.c index 68be73b3f48..cd4d7915ad3 100644 --- a/lib/fuzzing/fuzz_stable_sort_r.c +++ b/lib/fuzzing/fuzz_stable_sort_r_unstable.c @@ -1,6 +1,6 @@ /* Fuzzing for stable_sort - Copyright © Catalyst IT + Copyright © Catalyst IT 2024 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,12 +27,45 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) } /* - * For a "context" we use a byte that the values are XORed with before - * comparison, for a non-obvious but stable sort order. + * This function tries to never be a proper comparison function, + * whatever the value of ctx. + * + * If ctx is an odd number, it will change on every comparison, + * otherwise it will consistently use the same bad comparison + * technique. */ -static int cmp_int8(int8_t *a, int8_t *b, int8_t *c) +static int cmp_int8(int8_t *_a, int8_t *_b, int8_t *ctx) { - return (*a ^ *c) - (*b ^ *c); + int8_t a = *_a; + int8_t b = *_b; + int8_t c = *ctx; + + if (c & 1) { + /* aim for sustained chaos. */ + c += a; + c ^= b; + c ^= (c >> 5) + (c << 3); + *ctx = (c + 99) | 1; + } + switch((c >> 1) & 7) { + case 0: + return -1; + case 1: + return 1; + case 2: + return a + b; + case 3: + return c - b; + case 4: + return (a ^ b) > c; + case 5: + return -(a > c); + case 6: + return 2 * a - b; + case 7: + break; + } + return a - c; } @@ -45,7 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) int8_t aux[MAX_SIZE]; int8_t context; - if (len < 1 || len > MAX_SIZE) { + if (len < 3 || len > MAX_SIZE) { return 0; } context = (int8_t)buf[0]; @@ -57,13 +90,5 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) stable_sort_r(buf2, aux, len, 1, (samba_compare_with_context_fn_t)cmp_int8, &context); - - for (i = 1; i < len; i++) { - int c = cmp_int8(&buf2[i - 1], &buf2[i], &context); - if (c > 0) { - abort(); - } - } - return 0; } diff --git a/lib/fuzzing/wscript_build b/lib/fuzzing/wscript_build index 5a9801321aa..897a114ca7e 100644 --- a/lib/fuzzing/wscript_build +++ b/lib/fuzzing/wscript_build @@ -153,6 +153,11 @@ bld.SAMBA_BINARY('fuzz_stable_sort_r', deps='fuzzing stable_sort afl-fuzz-main', fuzzer=True) +bld.SAMBA_BINARY('fuzz_stable_sort_r_unstable', + source='fuzz_stable_sort_r_unstable.c', + deps='fuzzing stable_sort afl-fuzz-main', + fuzzer=True) + bld.SAMBA_BINARY('fuzz_security_token_vs_descriptor', source='fuzz_security_token_vs_descriptor.c', deps='fuzzing samba-security afl-fuzz-main', diff --git a/lib/ldb-samba/ldif_handlers.c b/lib/ldb-samba/ldif_handlers.c index f77f86fdcc0..35531222611 100644 --- a/lib/ldb-samba/ldif_handlers.c +++ b/lib/ldb-samba/ldif_handlers.c @@ -91,8 +91,14 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx, struct dom_sid sid; if (in->length > DOM_SID_STR_BUFLEN) { return -1; + } + if (in->length < 5) { /* "S-1-x" */ + return -1; + } + if (in->data[0] != 'S' && in->data[0] != 's') { + return -1; } else { - char p[in->length+1]; + char p[DOM_SID_STR_BUFLEN + 1]; memcpy(p, in->data, in->length); p[in->length] = '\0'; @@ -138,17 +144,6 @@ int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, return 0; } -bool ldif_comparision_objectSid_isString(const struct ldb_val *v) -{ - if (v->length < 3) { - return false; - } - - if (strncmp("S-", (const char *)v->data, 2) != 0) return false; - - return true; -} - /* compare two objectSids @@ -157,40 +152,31 @@ bool ldif_comparision_objectSid_isString(const struct ldb_val *v) static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *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 = {}; + struct ldb_val parsed_1 = {.data = NULL}; + struct ldb_val parsed_2 = {.data = NULL}; 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 '-'. + * or "s-"), we treat them as strings. + * + * It is not really possible for a blob to be both a SID string and a + * SID struct -- the first two bytes of a struct dom_sid (including in + * NDR form) 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 = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1); + if (ret == 0) { + v1 = &parsed_1; } - if (v2_is_string) { - int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2); - if (r == 0) { - v2 = &parsed_2; - } + ret = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2); + if (ret == 0) { + v2 = &parsed_2; } 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); - } + TALLOC_FREE(parsed_1.data); + TALLOC_FREE(parsed_2.data); return ret; } @@ -200,13 +186,11 @@ static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - if (ldif_comparision_objectSid_isString(in)) { - if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) { - /* Perhaps not a string after all */ - return ldb_handler_copy(ldb, mem_ctx, in, out); - } + /* First try as a string SID */ + if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) { return 0; } + /* not a string after all */ return ldb_handler_copy(ldb, mem_ctx, in, out); } @@ -215,10 +199,9 @@ static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx, { struct dom_sid sid; enum ndr_err_code ndr_err; - if (ldif_comparision_objectSid_isString(in)) { - if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) { - return 0; - } + + if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) { + return 0; } /* Perhaps not a string after all */ @@ -562,7 +545,7 @@ static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { return ldif_write_NDR(ldb, mem_ctx, in, out, - sizeof(struct repsFromToBlob), + sizeof(struct schemaInfoBlob), (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob, (ndr_print_fn_t)ndr_print_schemaInfoBlob, true); diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c index 6ae12c88eec..e6d412bd3cf 100644 --- a/lib/ldb/common/attrib_handlers.c +++ b/lib/ldb/common/attrib_handlers.c @@ -389,22 +389,57 @@ utf8str: * No need to recheck from the start, just from the first utf8 charu * found. Note that the callback of ldb_casefold() needs to be ascii * compatible. + * + * Probably ldb_casefold() is wrap_casefold() which wraps + * strupper_talloc_n(). */ b1 = ldb_casefold(ldb, mem_ctx, s1, n1); b2 = ldb_casefold(ldb, mem_ctx, s2, n2); if (!b1 || !b2) { - /* One of the strings was not UTF8, so we have no - * options but to do a binary compare */ + /* + * One of the strings was not UTF8, so we have no + * options but to do a binary compare. + * + * FIXME: this can be non-transitive. + * + * consider { + * CA 8A "ʊ" + * C6 B1 "Ʊ" + * C8 FE invalid utf-8 + * } + * + * The byte "0xfe" is always invalid in utf-8, so the + * comparisons against that string end up coming this way, + * while the "Ʊ" vs "ʊ" comparison goes via the ldb_casefold + * branch. Then: + * + * "ʊ" == "Ʊ" by casefold. + * "ʊ" > {c8 fe} by byte comparison. + * "Ʊ" < {c8 fe} by byte comparison. + * + * In many cases there are no invalid encodings between the + * upper and lower case letters, but the string as a whole + * might also compare differently due to the space-eating in + * the other branch. + */ talloc_free(b1); talloc_free(b2); ret = memcmp(s1, s2, MIN(n1, n2)); if (ret == 0) { - if (n1 == n2) return 0; + if (n1 == n2) { + return 0; + } if (n1 > n2) { - return (int)ldb_ascii_toupper(s1[n2]); + if (s1[n2] == '\0') { + return 0; + } + return 1; } else { - return -(int)ldb_ascii_toupper(s2[n1]); + if (s2[n1] == '\0') { + return 0; + } + return -1; } } return ret; @@ -426,7 +461,7 @@ utf8str: while (*u1 == ' ') u1++; while (*u2 == ' ') u2++; } - ret = (int)(*u1 - *u2); + ret = NUMERIC_CMP(*u1, *u2); talloc_free(b1); talloc_free(b2); diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index d2517089da5..cb4266dca91 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -1145,13 +1145,23 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1) * | normal DNs, sorted | casefold failed DNs | invalid DNs | NULLs | */ - if (dn0 == dn1 || (dn0->invalid && dn1->invalid)) { + if (dn0 == dn1) { + /* this includes the both-NULL case */ return 0; } - if (dn0 == NULL || dn0->invalid) { + if (dn0 == NULL) { return 1; } - if (dn1 == NULL || dn1->invalid) { + if (dn1 == NULL) { + return -1; + } + if (dn0->invalid && dn1->invalid) { + return 0; + } + if (dn0->invalid) { + return 1; + } + if (dn1->invalid) { return -1; } diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 0fc31e3fe09..bdd69f07734 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -2852,6 +2852,10 @@ class DnTests(TestCase): x = ldb.Dn(self.ldb, "dc=foo14,bar=bloe") self.assertEqual(x.get_casefold(), "DC=FOO14,BAR=bloe") + def test_get_casefold_dotted_i(self): + x = ldb.Dn(self.ldb, "dc=foo14,bir=blie") + self.assertEqual(x.get_casefold(), "DC=FOO14,BIR=blie") + def test_validate(self): x = ldb.Dn(self.ldb, "dc=foo15,bar=bloe") self.assertTrue(x.validate()) diff --git a/lib/ldb/tools/ldbsearch.c b/lib/ldb/tools/ldbsearch.c index 374f2405e47..a0c74b175fa 100644 --- a/lib/ldb/tools/ldbsearch.c +++ b/lib/ldb/tools/ldbsearch.c @@ -45,8 +45,7 @@ static void usage(struct ldb_context *ldb) } static int do_compare_msg(struct ldb_message **el1, - struct ldb_message **el2, - void *opaque) + struct ldb_message **el2) { return ldb_dn_compare((*el1)->dn, (*el2)->dn); } @@ -269,7 +268,7 @@ again: unsigned int i; if (sctx->num_stored) { - LDB_TYPESAFE_QSORT(sctx->store, sctx->num_stored, ldb, do_compare_msg); + TYPESAFE_QSORT(sctx->store, sctx->num_stored, do_compare_msg); } for (i = 0; i < sctx->num_stored; i++) { display_message(sctx->store[i], sctx); diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c index 80226278faf..a62771801d8 100644 --- a/lib/util/charset/codepoints.c +++ b/lib/util/charset/codepoints.c @@ -16480,22 +16480,8 @@ _PUBLIC_ bool isupper_m(codepoint_t val) */ _PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2) { - /* - * FIXME: this is unsuitable for use in a sort, as the - * comparison is intransitive. - * - * The problem is toupper_m() is only called on equality case, - * which has strange effects. - * - * Consider {'a', 'A', 'B'}. - * 'a' == 'A' - * 'a' > 'B' (lowercase letters come after upper) - * 'A' < 'B' - */ - if (c1 == c2 || - toupper_m(c1) == toupper_m(c2)) { - return 0; - } + c1 = toupper_m(c1); + c2 = toupper_m(c2); return NUMERIC_CMP(c1, c2); } diff --git a/lib/util/charset/tests/charset.c b/lib/util/charset/tests/charset.c index bca5449c579..46f89cb9ef4 100644 --- a/lib/util/charset/tests/charset.c +++ b/lib/util/charset/tests/charset.c @@ -47,7 +47,16 @@ static bool test_codepoint_cmpi(struct torture_context *tctx) torture_assert_int_equal(tctx, codepoint_cmpi('a', 'a'), 0, "same char"); torture_assert_int_equal(tctx, codepoint_cmpi('A', 'a'), 0, "upcase version"); torture_assert_int_equal(tctx, codepoint_cmpi('b', 'a'), 1, "right diff"); - torture_assert_int_equal(tctx, codepoint_cmpi('a', 'b'), -1, "right diff"); + torture_assert_int_equal(tctx, codepoint_cmpi('b', 'A'), 1, "left greater, mixed case"); + torture_assert_int_equal(tctx, codepoint_cmpi('C', 'a'), 1, "left greater, mixed case"); + torture_assert_int_equal(tctx, codepoint_cmpi('a', 'b'), -1, "right greater"); + torture_assert_int_equal(tctx, codepoint_cmpi('A', 'B'), -1, "right greater, upper case"); + torture_assert_int_equal(tctx, codepoint_cmpi(0xc5, 0xc5), 0, + "Latin Capital Letter A with Ring Above"); + torture_assert_int_equal(tctx, codepoint_cmpi(0xc5, 0xe5), 0, + "Latin both Letter A with Ring Above, lower right"); + torture_assert_int_equal(tctx, codepoint_cmpi(0xe5, 0xde), -1, + "å < Þ"); return true; } diff --git a/python/samba/tests/sid_strings.py b/python/samba/tests/sid_strings.py index 108351cc102..fbeb0a94077 100644 --- a/python/samba/tests/sid_strings.py +++ b/python/samba/tests/sid_strings.py @@ -410,9 +410,9 @@ class SidStringsAsDnInSearchBase(SidStringBase): """ skip_local = True cases = {' S-1-1-1-1-1-1-1': ldb.ERR_INVALID_DN_SYNTAX, - 'S-0-5-32-579': ldb.ERR_INVALID_DN_SYNTAX, + 'S-0-5-32-545': ldb.ERR_INVALID_DN_SYNTAX, 'S-000000000001-5-20-243': ldb.ERR_INVALID_DN_SYNTAX, - 'S-000000001-5-32-579': ldb.ERR_INVALID_DN_SYNTAX, + 'S-000000001-5-32-545': ldb.ERR_INVALID_DN_SYNTAX, 'S-01-05-020-0243': ldb.ERR_NO_SUCH_OBJECT, 'S-01-5-32-11579': ldb.ERR_NO_SUCH_OBJECT, 'S-0x1-0-0-579': ldb.ERR_INVALID_DN_SYNTAX, @@ -423,11 +423,11 @@ class SidStringsAsDnInSearchBase(SidStringBase): 'S-1-0': ldb.ERR_NO_SUCH_OBJECT, 'S-1-0-0-579': ldb.ERR_NO_SUCH_OBJECT, 'S-1-0x05-32-11579': ldb.ERR_NO_SUCH_OBJECT, - 'S-1-0x5-0x20-0x243': ldb.ERR_NO_SUCH_OBJECT, + 'S-1-0x5-0x20-0x221': None, 'S-1-0x50000000-32-579': ldb.ERR_NO_SUCH_OBJECT, - 'S-1-0x500000000-0x500000000-579': ldb.ERR_NO_SUCH_OBJECT, + 'S-1-0x500000000-0x500000000-579': ldb.ERR_INVALID_DN_SYNTAX, 'S-1-0x500000000-32-579': ldb.ERR_NO_SUCH_OBJECT, - 'S-1-0xABcDef123-0xABCDef123-579': ldb.ERR_NO_SUCH_OBJECT, + 'S-1-0xABcDef123-0xABCDef123-579': ldb.ERR_INVALID_DN_SYNTAX, 'S-1-1-1-1-1-1-1': ldb.ERR_NO_SUCH_OBJECT, 'S-1-21474836480-32-579': ldb.ERR_NO_SUCH_OBJECT, 'S-1-22': ldb.ERR_NO_SUCH_OBJECT, @@ -439,7 +439,7 @@ class SidStringsAsDnInSearchBase(SidStringBase): 'S-1-3-99': ldb.ERR_NO_SUCH_OBJECT, 'S-1-5-0-579': ldb.ERR_NO_SUCH_OBJECT, 'S-1-5-040-579': ldb.ERR_NO_SUCH_OBJECT, - 'S-1-5-0x20-579': ldb.ERR_NO_SUCH_OBJECT, + 'S-1-5-0x20-545': None, 'S-1-5-11111111111111111111111111111111111-579': ldb.ERR_INVALID_DN_SYNTAX, 'S-1-5-18446744073709551615-579': ldb.ERR_INVALID_DN_SYNTAX, 'S-1-5-18446744073709551616-579': ldb.ERR_INVALID_DN_SYNTAX, @@ -453,7 +453,8 @@ class SidStringsAsDnInSearchBase(SidStringBase): 'S-1-99999999999999999999999999999999999999-32-11111111111': ldb.ERR_INVALID_DN_SYNTAX, 'S-10-5-32-579': ldb.ERR_INVALID_DN_SYNTAX, 'S-2-5-32-579': ldb.ERR_INVALID_DN_SYNTAX, - 's-1-5-32-579': ldb.ERR_INVALID_DN_SYNTAX, + 's-1-5-32-5791': ldb.ERR_NO_SUCH_OBJECT, + 's-1-5-32-545': None, 'AA': ldb.ERR_INVALID_DN_SYNTAX, } @@ -488,11 +489,11 @@ class SidStringsAsDnSearchWithDnObject(SidStringBase): 'S-1-0': (None, ldb.ERR_NO_SUCH_OBJECT), 'S-1-0-0-579': (None, ldb.ERR_NO_SUCH_OBJECT), 'S-1-0x05-32-579': (None, None), - 'S-1-0x5-0x20-0x243': (None, ldb.ERR_NO_SUCH_OBJECT), + 'S-1-0x5-0x20-0x221': (None, None), 'S-1-0x50000000-32-579': (None, ldb.ERR_NO_SUCH_OBJECT), - 'S-1-0x500000000-0x500000000-579': (None, ldb.ERR_NO_SUCH_OBJECT), + 'S-1-0x500000000-0x500000000-579': ('parse error', None), 'S-1-0x500000000-32-579': (None, ldb.ERR_NO_SUCH_OBJECT), - 'S-1-0xABcDef123-0xABCDef123-579': (None, ldb.ERR_NO_SUCH_OBJECT), + 'S-1-0xABcDef123-0xABCDef123-579': ('parse error', None), 'S-1-1-1-1-1-1-1': (None, ldb.ERR_NO_SUCH_OBJECT), 'S-1-21474836480-32-579': (None, ldb.ERR_NO_SUCH_OBJECT), 'S-1-22': (None, ldb.ERR_NO_SUCH_OBJECT), -- Samba Shared Repository