The branch, v4-3-test has been updated via 0befbeb samr4: Use <SID=%s> in GetGroupsForUser via c7d8aca python/tests: Add more assertions that we get back the value we expect via cbb9a2a python/tests: Add tests for 64 bit signed integers via 215c284 pidl/python: also add a ndr_PyLong_FromLongLong() for symnetric reasons via 14930fe pidl/python: Provide static inline helper function ndr_PyLong_FromUnsignedLongLong via bd44d03 pidl/python: Calculate maximum integer values using a lookup table via d2f2df6 selftest: Add assertion that we actually fix the replPropertyMetaData sort order via 47af9ce selftest: Add in steps to re-create this database via 74043c5 Update release-4-1-0rc3 to include data using schema modifications via b5c196a ldb: create a cache of known wellknown objects instead of continously searching in the db via e120381 dbcheck: Use set() operations to make dbcheck more efficient via 9a8165b dbcheck: Try to avoid duplicate searches via 3c29480 dbcheck: Add additional tests for the attributeID list via df141f7 dbcheck: Add explict tests for unknown and unsorted attributeID values via 429db95 pidl: Assert that python arrays will not overflow the C array via 1e432b9 pydsdb: Allow the full range of uint32_t values for attributeID via 43c6f8c python/tests: Add tests for integer overflow handling via c9b80d7 pidl: Change PIDL to correctly use and validate python integer types via a779039 python: Use an unsigned integer for buf_size, not -1 from c9ed862 WHATSNEW: Prepare release notes for Samba 4.3.0rc5
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-3-test - Log ----------------------------------------------------------------- commit 0befbeb33bf3ebb189639598281e989178efbc4a Author: Volker Lendecke <v...@samba.org> Date: Tue Sep 1 08:41:04 2015 +0200 samr4: Use <SID=%s> in GetGroupsForUser This way we avoid quoting problems in user's DNs Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Tue Sep 1 23:49:14 CEST 2015 on sn-devel-104 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11488 (cherry picked from commit 841845dea35089a187fd1626c9752d708989ac7b) Autobuild-User(v4-3-test): Stefan Metzmacher <me...@samba.org> Autobuild-Date(v4-3-test): Thu Sep 3 12:14:12 CEST 2015 on sn-devel-104 commit c7d8aca2de88b72e69921558e5cf708177ecd5bc Author: Andrew Bartlett <abart...@samba.org> Date: Tue Sep 1 15:00:30 2015 +1200 python/tests: Add more assertions that we get back the value we expect BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Tue Sep 1 17:00:53 CEST 2015 on sn-devel-104 (cherry picked from commit 5aefea842528d053b86b50ff2ed9047db1ca4594) commit cbb9a2a65f900d961a50b9e1c51c20b8208a6b03 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Sep 1 14:58:20 2015 +1200 python/tests: Add tests for 64 bit signed integers BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 1f50e194517b84ccc8d0208d563e83dabfb2327a) commit 215c284eaded01e251b07e5db4cd5d04d6812601 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Sep 1 10:30:49 2015 +0200 pidl/python: also add a ndr_PyLong_FromLongLong() for symnetric reasons BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit e6fbeb860638ad1113914b9460a618025d950d08) commit 14930febe33b17ba5abf877a5ad4d7ffc55740b8 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Sep 1 14:33:35 2015 +1200 pidl/python: Provide static inline helper function ndr_PyLong_FromUnsignedLongLong This should isolate any coverity warnings on 64-bit platforms (where LONG_MAX is larger than any possible 32 bit value) to a single spot, or possibly eliminate it. This is needed for the unsigned 64 bit case, and on 32 bit systems, as PyInt_FromLong is limited to a signed "long" int. The compiler should be able to eliminate many of these calls with the embedded type knowlege. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit d1416d65a3cc61e4e56d1a43bb634d12f418ba0e) commit bd44d03159d7ba2048b1fd27e2623fe4bb7ec773 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Aug 28 11:46:56 2015 +1200 pidl/python: Calculate maximum integer values using a lookup table This avoids a << of 64 bits in the unused end of the conditional expression. This was flagged by Coverity and the fix was suggested by metze. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Andrew Bartlett Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit c2f4e324d9c1ced2e1da859594ef67ae9f645919) commit d2f2df68471085c0ac01d26be9a406f7fe781a7b Author: Andrew Bartlett <abart...@samba.org> Date: Mon Aug 3 13:50:08 2015 +1200 selftest: Add assertion that we actually fix the replPropertyMetaData sort order This ensures that the dbcheck rule fixes the sort order (and only fixes the sort order). BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Tue Aug 25 02:45:58 CEST 2015 on sn-devel-104 (cherry picked from commit dcc657a2219498beac8bde6cbf999ee7cf6acae8) commit 47af9ce98ad852f66c69a054a768429839d8bfdd Author: Andrew Bartlett <abart...@samba.org> Date: Mon Aug 3 11:25:02 2015 +1200 selftest: Add in steps to re-create this database This may assist if this needs to be changed again BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 5504502aa68f4901f52dc2e8f7ee8b3a9c74546e) commit 74043c5edc19be602b12d54dcf261ea58290d0f6 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Aug 3 11:24:10 2015 +1200 Update release-4-1-0rc3 to include data using schema modifications This allows us to know that the previous patches are correct. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit a6957ba5da3130994d2f35328aea6f4cd604147a) commit b5c196ac277a756159a03aa02c0ba424247491f5 Author: Matthieu Patou <m...@matws.net> Date: Mon May 25 09:17:55 2015 -0700 ldb: create a cache of known wellknown objects instead of continously searching in the db Profiling on dbcheck have shown that we spend 10% of the time looking for wellknown objects. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Change-Id: I13ed58e8062d1b7b6179d17b0e7e56f943572c6c Signed-off-by: Matthieu Patou <m...@matws.net> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 6122acad0f1a7bc23b6f58862c16968e13da979d) commit e120381231056277a604fb5a73d5847439cd1851 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Jul 27 15:11:56 2015 +1200 dbcheck: Use set() operations to make dbcheck more efficient BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit c049106bf8267b30a9242d2d574661291cced780) commit 9a8165b31ffaa5283fed3badb822fcca01a702a0 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Jul 27 15:44:56 2015 +1200 dbcheck: Try to avoid duplicate searches BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit fb88f9cbd969267aaffa021724cf34087c653ba8) commit 3c29480ab7ef9562779278a5064d18ea5c3d2f29 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 28 16:11:54 2015 +1200 dbcheck: Add additional tests for the attributeID list BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 2ff9b171378922e68205d5f0eefd2231607b5b89) commit df141f779f94acaea2c3876263d77fc8d8b6e3b7 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Jul 23 16:01:14 2015 +1200 dbcheck: Add explict tests for unknown and unsorted attributeID values Unknown attributeID values would cause an exception previously, and unsorted attributes cause a failure to replicate with Samba 4.2. In commit 61b978872fe86906611f64430b2608f5e7ea7ad8 we started to sort these values correctly, but previous versions of Samba did not sort them correctly (we sorted high-bit-set values as negative), and then after 9c9df40220234cba973e84b4985d90da1334a1d1 we stoped accepting these. To ensure we are allowed to make this unusual change to the replPropertyMetaData, a new OID is allocated and checked for in repl_meta_data.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=10973 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 2766bad5ef1e1949746c059c29f179ddae476239) commit 429db9527866fea464f4f1f7b06107c28e2ef30d Author: Andrew Bartlett <abart...@samba.org> Date: Thu Jul 30 14:28:48 2015 +1200 pidl: Assert that python arrays will not overflow the C array We do not write network services in Python, so this is not a security issue, but would cause a crash or other odd behaviour if the length was changed BUG: https://bugzilla.samba.org/show_bug.cgi?id=11430 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit e3cf25bdc04795f884fe2a4ce0605d5175b45e93) commit 1e432b9fd4796474888d66c30614ec5a8ae2059b Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 28 14:29:25 2015 +1200 pydsdb: Allow the full range of uint32_t values for attributeID The high bit may be set in these integers, so we need an unsigned int to store it in BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit bed29f3c92861fb2b83ad03a5c759061e1c31eba) commit 43c6f8cf69b4d49824e601480ca51c105fa9932f Author: Andrew Bartlett <abart...@samba.org> Date: Thu Jul 30 14:29:54 2015 +1200 python/tests: Add tests for integer overflow handling This also documents an issue with our python bindings and lists, as changes to integers in a list of integers are not preserved BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 336d41155e94303d0e1fa0530874539339439fed) commit c9b80d79ec2d8f453dabac495b611fe9b04ba318 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Jul 27 10:57:43 2015 +1200 pidl: Change PIDL to correctly use and validate python integer types In particular, it is critical that we use unsigned integers of sufficient size in python for unsigned C integers, and it is critical that we check for overflow at both the python and C level. Otherwise, we may both represent and sort these incorrectly, in particular when sorting attributeID values from DRSUAPI which are represented as an signed enum in C and a uint32_t in IDL, but which often has the high bit set (in schema extensions). BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 5206ccd002b015a16952d21bd2fa441ff2e39eab) commit a7790399c64cebdaae6f011a13397c877e7b56ce Author: Andrew Bartlett <abart...@samba.org> Date: Wed Jul 29 15:25:09 2015 +1200 python: Use an unsigned integer for buf_size, not -1 This will fail once our python bindings correctly check value ranges BUG: https://bugzilla.samba.org/show_bug.cgi?id=11429 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 3faa7dc5a7d39cfdfc908a51e38772fda801c1a3) ----------------------------------------------------------------------- Summary of changes: pidl/lib/Parse/Pidl/Samba4/Python.pm | 215 +- python/samba/dbchecker.py | 116 +- python/samba/samdb.py | 15 +- python/samba/tests/dcerpc/integer.py | 235 + python/samba/tests/dcerpc/sam.py | 2 +- python/samba/tests/dsdb.py | 24 + selftest/knownfail | 5 + selftest/tests.py | 1 + source4/dsdb/pydsdb.c | 4 +- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 31 +- source4/dsdb/samdb/samdb.h | 6 + source4/rpc_server/samr/dcesrv_samr.c | 10 +- ...xpected-replpropertymetadata-after-dbcheck.ldif | 122 + ...pected-replpropertymetadata-before-dbcheck.ldif | 122 + .../provisions/release-4-1-0rc3/private/dns.keytab | Bin 1037 -> 1037 bytes ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 16082 ++++++------- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 22532 +++++++++--------- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 364 +- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 198 +- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 4 +- .../private/dns/sam.ldb.d/metadata.tdb.dump | 4 +- .../release-4-1-0rc3/private/dns/sam.ldb.dump | 4 +- .../release-4-1-0rc3/private/hklm.ldb.dump | 2 +- .../release-4-1-0rc3/private/idmap.ldb.dump | 36 +- .../provisions/release-4-1-0rc3/private/named.conf | 6 +- .../provisions/release-4-1-0rc3/private/named.txt | 8 +- .../release-4-1-0rc3/private/privilege.ldb.dump | 2 +- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 16154 ++++++------- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 22932 +++++++++---------- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 364 +- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 198 +- ...DRELEASE-4-1-0RC3,DC%3DSAMBA,DC%3DCORP.ldb.dump | 2798 +-- .../private/sam.ldb.d/metadata.tdb.dump | 4 +- .../release-4-1-0rc3/private/sam.ldb.dump | 8 +- .../release-4-1-0rc3/private/secrets.keytab | Bin 1482 -> 1482 bytes .../release-4-1-0rc3/private/secrets.ldb.dump | 10 +- .../release-4-1-0rc3/private/secrets.tdb.dump | 4 +- .../release-4-1-0rc3/private/share.ldb.dump | 2 +- .../private/smbd.tmp/msg/names.tdb.dump | 24 +- .../release-4-1-0rc3/steps-to-reproduce.txt | 30 + .../provisions/release-4-1-0rc3/sudo.schema.2.ldif | 52 + .../provisions/release-4-1-0rc3/sudo.schema.ldif | 235 + .../provisions/release-4-1-0rc3/sudoers-mod.ldif | 4 + .../provisions/release-4-1-0rc3/sudoers.ldif | 13 + source4/setup/schema_samba4.ldif | 1 + testprogs/blackbox/dbcheck-oldrelease.sh | 47 +- 46 files changed, 41773 insertions(+), 41257 deletions(-) create mode 100644 python/samba/tests/dcerpc/integer.py create mode 100644 source4/selftest/provisions/release-4-1-0rc3/expected-replpropertymetadata-after-dbcheck.ldif create mode 100644 source4/selftest/provisions/release-4-1-0rc3/expected-replpropertymetadata-before-dbcheck.ldif create mode 100644 source4/selftest/provisions/release-4-1-0rc3/steps-to-reproduce.txt create mode 100644 source4/selftest/provisions/release-4-1-0rc3/sudo.schema.2.ldif create mode 100644 source4/selftest/provisions/release-4-1-0rc3/sudo.schema.ldif create mode 100644 source4/selftest/provisions/release-4-1-0rc3/sudoers-mod.ldif create mode 100644 source4/selftest/provisions/release-4-1-0rc3/sudoers.ldif Changeset truncated at 500 lines: diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index ff68e7a..180b6b2 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -10,7 +10,7 @@ use Exporter; use strict; use Parse::Pidl qw(warning fatal error); -use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias); +use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias bitmap_type_fn enum_type_fn); use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); use Parse::Pidl::CUtil qw(get_value_of get_pointer_to); @@ -953,14 +953,58 @@ sub ConvertObjectFromPythonData($$$$$$;$) $actual_ctype = $actual_ctype->{DATA}; } - if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP") { + # We need to cover ENUMs, BITMAPS and SCALAR values here, as + # all could otherwise be assigned invalid integer values + my $ctype_alias = ""; + my $uint_max = ""; + if ($actual_ctype->{TYPE} eq "ENUM") { + # Importantly, ENUM values are unsigned in pidl, and + # typically map to uint32 + $ctype_alias = enum_type_fn($actual_ctype); + } elsif ($actual_ctype->{TYPE} eq "BITMAP") { + $ctype_alias = bitmap_type_fn($actual_ctype); + } elsif ($actual_ctype->{TYPE} eq "SCALAR") { + $ctype_alias = expandAlias($actual_ctype->{NAME}); + } + + # This is the unsigned Python Integer -> C integer validation + # case. The signed case is below. + if ($ctype_alias =~ /^(uint[0-9]*|hyper|udlong|udlongr + |NTTIME_hyper|NTTIME|NTTIME_1sec + |uid_t|gid_t)$/x) { + $self->pidl("{"); + $self->indent; + $self->pidl("const unsigned long long uint_max = ndr_sizeof2uintmax(sizeof($target));"); $self->pidl("if (PyLong_Check($cvar)) {"); $self->indent; - $self->pidl("$target = PyLong_AsLongLong($cvar);"); + $self->pidl("unsigned long long test_var;"); + $self->pidl("test_var = PyLong_AsUnsignedLongLong($cvar);"); + $self->pidl("if (PyErr_Occurred() != NULL) {"); + $self->indent; + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (test_var > uint_max) {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %llu\",\\"); + $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("$target = test_var;"); $self->deindent; $self->pidl("} else if (PyInt_Check($cvar)) {"); $self->indent; - $self->pidl("$target = PyInt_AsLong($cvar);"); + $self->pidl("long test_var;"); + $self->pidl("test_var = PyInt_AsLong($cvar);"); + $self->pidl("if (test_var < 0 || test_var > uint_max) {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %ld\",\\"); + $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("$target = test_var;"); $self->deindent; $self->pidl("} else {"); $self->indent; @@ -969,34 +1013,61 @@ sub ConvertObjectFromPythonData($$$$$$;$) $self->pidl($fail); $self->deindent; $self->pidl("}"); + $self->deindent; + $self->pidl("}"); return; } - if ($actual_ctype->{TYPE} eq "SCALAR" ) { - if (expandAlias($actual_ctype->{NAME}) =~ /^(u?int64|hyper|dlong|udlong|udlongr - |NTTIME_hyper|NTTIME|NTTIME_1sec - |uid_t|gid_t)$/x) { - $self->pidl("if (PyLong_Check($cvar)) {"); - $self->indent; - $self->pidl("$target = PyLong_AsLongLong($cvar);"); - $self->deindent; - $self->pidl("} else if (PyInt_Check($cvar)) {"); - $self->indent; - $self->pidl("$target = PyInt_AsLong($cvar);"); - $self->deindent; - $self->pidl("} else {"); - $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); - $self->pidl($fail); - $self->deindent; - $self->pidl("}"); - return; - } - if (expandAlias($actual_ctype->{NAME}) =~ /^(char|u?int[0-9]*|time_t)$/) { - $self->pidl("PY_CHECK_TYPE(&PyInt_Type, $cvar, $fail);"); - $self->pidl("$target = PyInt_AsLong($cvar);"); - return; - } + + # Confirm the signed python integer fits in the C type + # correctly. It is subtly different from the unsigned case + # above, so while it looks like a duplicate, it is not + # actually a duplicate. + if ($ctype_alias =~ /^(dlong|char|int[0-9]*|time_t)$/x) { + $self->pidl("{"); + $self->indent; + $self->pidl("const long long int_max = ndr_sizeof2intmax(sizeof($target));"); + $self->pidl("const long long int_min = -int_max - 1;"); + $self->pidl("if (PyLong_Check($cvar)) {"); + $self->indent; + $self->pidl("long long test_var;"); + $self->pidl("test_var = PyLong_AsLongLong($cvar);"); + $self->pidl("if (PyErr_Occurred() != NULL) {"); + $self->indent; + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (test_var < int_min || test_var > int_max) {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %lld\",\\"); + $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("$target = test_var;"); + $self->deindent; + $self->pidl("} else if (PyInt_Check($cvar)) {"); + $self->indent; + $self->pidl("long test_var;"); + $self->pidl("test_var = PyInt_AsLong($cvar);"); + $self->pidl("if (test_var < int_min || test_var > int_max) {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %ld\",\\"); + $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->pidl("$target = test_var;"); + $self->deindent; + $self->pidl("} else {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); + $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + $self->deindent; + $self->pidl("}"); + return; } if ($actual_ctype->{TYPE} eq "STRUCT" or $actual_ctype->{TYPE} eq "INTERFACE") { @@ -1152,6 +1223,13 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_GET_SIZE($py_var));"); $self->pidl("if (!$var_name) { $fail; }"); $self->pidl("talloc_set_name_const($var_name, \"ARRAY: $var_name\");"); + } else { + $self->pidl("if (ARRAY_SIZE($var_name) != PyList_GET_SIZE($py_var)) {"); + $self->indent; + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected list of type %s, length %zu, got %zd\", Py_TYPE($py_var)->tp_name, ARRAY_SIZE($var_name), PyList_GET_SIZE($py_var));"); + $self->pidl("$fail"); + $self->deindent; + $self->pidl("}"); } $self->pidl("for ($counter = 0; $counter < PyList_GET_SIZE($py_var); $counter++) {"); $self->indent; @@ -1202,17 +1280,29 @@ sub ConvertScalarToPython($$$) $ctypename = expandAlias($ctypename); if ($ctypename =~ /^(int64|dlong)$/) { - return "PyLong_FromLongLong($cvar)"; + return "ndr_PyLong_FromLongLong($cvar)"; } - if ($ctypename =~ /^(uint64|hyper|udlong|udlongr|NTTIME_hyper|NTTIME|NTTIME_1sec|uid_t|gid_t)$/) { - return "PyLong_FromUnsignedLongLong($cvar)"; + if ($ctypename =~ /^(uint64|hyper|NTTIME_hyper|NTTIME|NTTIME_1sec|udlong|udlongr|uid_t|gid_t)$/) { + return "ndr_PyLong_FromUnsignedLongLong($cvar)"; } - if ($ctypename =~ /^(char|u?int[0-9]*|time_t)$/) { + if ($ctypename =~ /^(char|int|int8|int16|int32|time_t)$/) { return "PyInt_FromLong($cvar)"; } + # Needed to ensure unsigned values in a 32 or 16 bit enum is + # cast correctly to a uint32_t, not sign extended to a a + # possibly 64 bit unsigned long. (enums are signed in C, + # unsigned in NDR) + if ($ctypename =~ /^(uint32|uint3264)$/) { + return "ndr_PyLong_FromUnsignedLongLong((uint32_t)$cvar)"; + } + + if ($ctypename =~ /^(uint|uint8|uint16|uint1632)$/) { + return "PyInt_FromLong((uint16_t)$cvar)"; + } + if ($ctypename eq "DATA_BLOB") { return "PyString_FromStringAndSize((char *)($cvar).data, ($cvar).length)"; } @@ -1408,6 +1498,61 @@ sub Parse($$$$$) #include \"$hdr\" #include \"$ndr_hdr\" +/* + * These functions are here to ensure they can be optomised out by + * the compiler based on the constant input values + */ + +static inline unsigned long long ndr_sizeof2uintmax(size_t var_size) +{ + switch (var_size) { + case 8: + return UINT64_MAX; + case 4: + return UINT32_MAX; + case 2: + return UINT16_MAX; + case 1: + return UINT8_MAX; + } + + return 0; +} + +static inline long long ndr_sizeof2intmax(size_t var_size) +{ + switch (var_size) { + case 8: + return INT64_MAX; + case 4: + return INT32_MAX; + case 2: + return INT16_MAX; + case 1: + return INT8_MAX; + } + + return 0; +} + +static inline PyObject *ndr_PyLong_FromLongLong(long long v) +{ + if (v > LONG_MAX || v < LONG_MIN) { + return PyLong_FromLongLong(v); + } else { + return PyInt_FromLong(v); + } +} + +static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) +{ + if (v > LONG_MAX) { + return PyLong_FromUnsignedLongLong(v); + } else { + return PyInt_FromLong(v); + } +} + "); foreach my $x (@$ndr) { @@ -1487,7 +1632,7 @@ sub Parse($$$$$) my $py_obj; my ($ctype, $cvar) = @{$h->{'val'}}; if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) { - $py_obj = "PyInt_FromLong($cvar)"; + $py_obj = "ndr_PyLong_FromUnsignedLongLong($cvar)"; } elsif ($cvar =~ /^".*"$/) { $py_obj = "PyString_FromString($cvar)"; } else { diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index 74e9678..4fb9d12 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -24,6 +24,7 @@ from base64 import b64decode from samba import dsdb from samba import common from samba.dcerpc import misc +from samba.dcerpc import drsuapi from samba.ndr import ndr_unpack, ndr_pack from samba.dcerpc import drsblobs from samba.common import dsdb_Dn @@ -63,6 +64,7 @@ class dbcheck(object): self.move_to_lost_and_found = False self.fix_instancetype = False self.fix_replmetadata_zero_invocationid = False + self.fix_replmetadata_unsorted_attid = False self.fix_deleted_deleted_objects = False self.fix_dn = False self.fix_base64_userparameters = False @@ -80,6 +82,8 @@ class dbcheck(object): self.wellknown_sds = get_wellknown_sds(self.samdb) self.fix_all_missing_objectclass = False + self.dn_set = set() + self.name_map = {} try: res = samdb.search(base="CN=DnsAdmins,CN=Users,%s" % samdb.domain_dn(), scope=ldb.SCOPE_BASE, @@ -125,12 +129,12 @@ class dbcheck(object): def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']): '''perform a database check, returning the number of errors found''' - res = self.samdb.search(base=DN, scope=scope, attrs=['dn'], controls=controls) self.report('Checking %u objects' % len(res)) error_count = 0 for object in res: + self.dn_set.add(str(object.dn)) error_count += self.check_object(object.dn, attrs=attrs) if DN is None: @@ -698,18 +702,21 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) return 0 def process_metadata(self, val): - '''Read metadata properties and list attributes in it''' + '''Read metadata properties and list attributes in it. + raises KeyError if the attid is unknown.''' - list_att = [] + set_att = set() + list_attid = [] repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(val)) obj = repl.ctr for o in repl.ctr.array: att = self.samdb_schema.get_lDAPDisplayName_by_attid(o.attid) - list_att.append(att.lower()) + set_att.add(att.lower()) + list_attid.append(o.attid) - return list_att + return (set_att, list_attid) def fix_metadata(self, dn, attr): @@ -989,11 +996,52 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) nmsg = ldb.Message() nmsg.dn = dn nmsg[attr] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, attr) - if self.do_modify(nmsg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"], + if self.do_modify(nmsg, ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA, + "local_oid:1.3.6.1.4.1.7165.4.3.14:0"], "Failed to fix attribute %s" % attr): self.report("Fixed attribute '%s' of '%s'\n" % (attr, dn)) + def err_replmetadata_unknown_attid(self, dn, attr, repl_meta_data): + repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, + str(repl_meta_data)) + ctr = repl.ctr + for o in ctr.array: + # Search for an invalid attid + try: + att = self.samdb_schema.get_lDAPDisplayName_by_attid(o.attid) + except KeyError: + self.report('ERROR: attributeID 0X%0X is not known in our schema, not fixing %s on %s\n' % (o.attid, attr, dn)) + return + + + def err_replmetadata_unsorted_attid(self, dn, attr, repl_meta_data): + repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, + str(repl_meta_data)) + ctr = repl.ctr + found = False + + self.report('ERROR: unsorted attributeID values in %s on %s\n' % (attr, dn)) + if not self.confirm_all('Fix %s on %s by sorting the attribute list?' + % (attr, dn), 'fix_replmetadata_unsorted_attid'): + self.report('Not fixing %s on %s\n' % (attr, dn)) + return + + # Sort the array, except for the last element + ctr.array[:-1] = sorted(ctr.array[:-1], key=lambda o: o.attid) + + replBlob = ndr_pack(repl) + + nmsg = ldb.Message() + nmsg.dn = dn + nmsg[attr] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, attr) + if self.do_modify(nmsg, ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA, + "local_oid:1.3.6.1.4.1.7165.4.3.14:0", + "local_oid:1.3.6.1.4.1.7165.4.3.25:0"], + "Failed to fix attribute %s" % attr): + self.report("Fixed attribute '%s' of '%s'\n" % (attr, dn)) + + def is_deleted_deleted_objects(self, obj): faulty = False if "description" not in obj: @@ -1125,8 +1173,8 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) return 1 obj = res[0] error_count = 0 - list_attrs_from_md = [] - list_attrs_seen = [] + set_attrs_from_md = set() + set_attrs_seen = set() got_repl_property_meta_data = False got_objectclass = False @@ -1181,7 +1229,31 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) # We don't continue, as we may also have other fixes for this attribute # based on what other attributes we see. - list_attrs_from_md = self.process_metadata(obj[attrname]) + try: + (set_attrs_from_md, list_attid_from_md) = self.process_metadata(obj[attrname]) + except KeyError: + error_count += 1 + self.err_replmetadata_unknown_attid(dn, attrname, obj[attrname]) + continue + + if sorted(list_attid_from_md[:-1]) != list_attid_from_md[:-1]: + error_count += 1 + self.err_replmetadata_unsorted_attid(dn, attrname, obj[attrname]) + else: + # Here we check that the first attid is 0 + # (objectClass) and that the last on is the RDN + # from the DN. + rdn_attid = self.samdb_schema.get_attid_from_lDAPDisplayName(dn.get_rdn_name()) + if list_attid_from_md[-1] != rdn_attid: + error_count += 1 + self.report("ERROR: Not fixing incorrect final attributeID in '%s' on '%s', it should match the RDN %s" % + (attrname, str(dn), dn.get_rdn_name())) + + if list_attid_from_md[0] != 0: + error_count += 1 + self.report("ERROR: Not fixing incorrect inital attributeID in '%s' on '%s', it should be objectClass" % + (attrname, str(dn))) + got_repl_property_meta_data = True continue @@ -1274,7 +1346,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) if (not flag & dsdb.DS_FLAG_ATTR_NOT_REPLICATED and not flag & dsdb.DS_FLAG_ATTR_IS_CONSTRUCTED and not self.samdb_schema.get_linkId_from_lDAPDisplayName(attrname)): - list_attrs_seen.append(str(attrname).lower()) + set_attrs_seen.add(str(attrname).lower()) if syntax_oid in [ dsdb.DSDB_SYNTAX_BINARY_DN, dsdb.DSDB_SYNTAX_OR_NAME, dsdb.DSDB_SYNTAX_STRING_DN, ldb.SYNTAX_DN ]: @@ -1345,17 +1417,17 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) else: self.report("Not fixing isDeleted originating_change_time on '%s'" % str(dn)) - for att in list_attrs_seen: - if not att in list_attrs_from_md: - if show_dn: - self.report("On object %s" % dn) - show_dn = False - error_count += 1 - self.report("ERROR: Attribute %s not present in replication metadata" % att) - if not self.confirm_all("Fix missing replPropertyMetaData element '%s'" % att, 'fix_all_metadata'): - self.report("Not fixing missing replPropertyMetaData element '%s'" % att) - continue - self.fix_metadata(dn, att) + + for att in set_attrs_seen.difference(set_attrs_from_md): + if show_dn: + self.report("On object %s" % dn) + show_dn = False + error_count += 1 + self.report("ERROR: Attribute %s not present in replication metadata" % att) + if not self.confirm_all("Fix missing replPropertyMetaData element '%s'" % att, 'fix_all_metadata'): + self.report("Not fixing missing replPropertyMetaData element '%s'" % att) + continue + self.fix_metadata(dn, att) if self.is_fsmo_role(dn): if "fSMORoleOwner" not in obj and ("*" in attrs or "fsmoroleowner" in map(str.lower, attrs)): @@ -1363,7 +1435,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) error_count += 1 try: - if dn != self.samdb.get_root_basedn(): + if dn != self.samdb.get_root_basedn() and str(dn.parent()) not in self.dn_set: res = self.samdb.search(base=dn.parent(), scope=ldb.SCOPE_BASE, controls=["show_recycled:1", "show_deleted:1"]) except ldb.LdbError, (enum, estr): diff --git a/python/samba/samdb.py b/python/samba/samdb.py index e3a6292..817fbdb 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py -- Samba Shared Repository